no message

This commit is contained in:
hellcat 2026-06-14 15:46:45 +08:00
parent 1215f3b666
commit 9d14720185
10009 changed files with 879934 additions and 162 deletions

View File

@ -0,0 +1,453 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api\Nasa\V1\Base;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use InvalidArgumentException;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
abstract class ListController
{
private string $sOperatorDefault = 'eq';
private string $sSortDefault = 'asc';
private array $aFilterParams = [
'c' => [],
'cc' => [],
'ob' => [],
];
protected $oModel;
protected string $sPageName = '';
protected string $sModelName = '';
protected array $aFilterFields = []; // 允许where的字段
// protected array $aArticleFields = []; // 文章字段
protected array $aFieldTypes = [];
protected array $aLenthFields = []; // 限制长度的字段
protected array $aSelectFields = []; // 默认作为select的字段
protected array $aListFields = []; // list展示的字段和名字映射
protected array $aDateFields = []; // date字段
protected array $aJsonFields = []; // json字段
protected array $aValueStyle = []; // 特定文字渲染样式
protected int $iLimitMax = 100; // 默认limit限制
protected int $iLimit = 20; // 默认显示行数
protected array $aCcExtFields = []; // 自定义条件字段追加在listFields后
protected array $aCcFields = [];
protected int $iOrderByMax = 3;
protected array $aOrderBy = [
[
"sField" => "id",
"sSort" => "desc"
]
];
public function __construct()
{
if ($this->sModelName) {
$sFullNamespace = "App\Models\Nasa\\{$this->sModelName}";
if (! class_exists($sFullNamespace)) {
throw new InvalidArgumentException("【系统架构错误】: 找不到领域模型 {$sFullNamespace}");
}
$this->oModel = new $sFullNamespace();
$this->aCcFields = array_merge($this->aListFields, $this->aCcExtFields);
}
}
private function mapOperator($sOperator)
{
$sSqlOperator = match ($sOperator) {
'like' => 'like',
'eq' => '=',
'ne' => '!=',
'gt' => '>',
'gte' => '>=',
'lt' => '<',
'lte' => '<=',
default => '',
};
return $sSqlOperator;
}
private function getOrderBySchema()
{
$iOrderByCount = count($this->aOrderBy);
$iDiff = $this->iOrderByMax - $iOrderByCount;
$a = $this->aOrderBy;
for ($i=0; $i<$iDiff; $i++) {
$a[] = [];
}
return $a;
}
private function getOrderBy()
{
return $this->aOrderBy;
}
public function getListFields()
{
$a = [];
foreach ($this->aListFields as $k => $v) {
if ($v) {
$a[$k] = $v;
} else {
$a[$k] = $k;
}
}
return $a;
}
private function getCcLast()
{
$aCcFieldsTmp = $this->aCcFields;
foreach ($this->aFilterParams['cc'] as $ACC) {
unset($aCcFieldsTmp[$ACC['sField']]);
}
$s = head(array_keys($aCcFieldsTmp));
return $s;
}
public function add(Request $oRequest): \Illuminate\Http\JsonResponse
{
$sTableName = $this->oModel->getTable();
$aRawFields = Schema::getColumnListing($sTableName);
$sClassName = get_class($this->oModel);
$aKickFields = [];
if (defined($sClassName . '::UPDATED_AT')) {
$aKickFields[] = constant($sClassName . '::UPDATED_AT');
}
if (defined($sClassName . '::CREATED_AT')) {
$aKickFields[] = constant($sClassName . '::CREATED_AT');
}
$aKickFields[] = "id";
$aRawFieldsClear = [];
foreach ($aRawFields as $aRawField) {
if (in_array($aRawField, $aKickFields)) {
continue;
}
$aRawFieldsClear[] = $aRawField;
}
return response()->json([
'iCode' => 200,
'aData' => [
'cList' => $aRawFieldsClear,
'sPageName' => $this->sPageName
]
], 200);
}
public function clone(Request $oRequest)
{
$iId = request('id');
$oModelResult = $this->oModel->findOrFail($iId);
$cList = $oModelResult->getRawOriginal();
$sTableName = $this->oModel->getTable();
$aStatus = DB::select("SHOW TABLE STATUS LIKE '{$sTableName}'");
$iNextId = $aStatus[0]->Auto_increment ?? 1;
$cList['id'] = $iNextId;
return response()->json([
'iCode' => 200,
'aData' => [
'cList' => $cList,
'aMap' => $this->oModel->getMapAll(),
'aListField' => $this->getListFields(),
'sPageName' => $this->sPageName
]
], 200);
}
public function cloneSave(Request $oRequest)
{
$iId = request('id');
$aParams = $oRequest->all();
foreach ($aParams as $k => $v) {
$this->oModal->{$k} = $v;
}
$this->oModel->create();
return response()->json([
'iCode' => 200,
'aData' => [],
'sMsg' => "保存成功id ".$this->oModel->id
], 200);
}
public function detail(Request $oRequest)
{
$iId = request('id');
$oModelResult = $this->oModel->findOrFail($iId);
$cList = $oModelResult->getRawOriginal();
return response()->json([
'iCode' => 200,
'aData' => [
'cList' => $cList,
'aMap' => $this->oModel->getMapAll(),
'aListField' => $this->getListFields(),
'sPageName' => $this->sPageName
]
], 200);
}
public function hit(Request $oRequest)
{
$iId = request('id');
$sField = request('field');
$sHit = $this->oModel->find($iId)?->{$sField};
return response()->json([
'iCode' => 200,
'aData' => [
'sHit' => $sHit
]
], 200);
}
public function delete(Request $oRequest)
{
$iId = request('id');
$this->oModel->findOrFail($iId)->delete();
return response()->json([
'iCode' => 200,
'aData' => [],
'sMsg' => '删除成功'
], 200);
}
public function addSave(Request $oRequest)
{
$aParams = $oRequest->all();
foreach ($aParams as $k => $v) {
$this->oModel->{$k} = $v;
}
if (!$this->oModel->save()) {
return response()->json(['code' => 500, 'msg' => '保存失败?'], 500);
}
return response()->json([
'iCode' => 200,
'aData' => [],
'sMsg' => '保存成功'
], 200);
}
public function detailSave(Request $oRequest)
{
$iId = request('id');
$oThisModel = $this->oModel->find($iId);
$aParams = $oRequest->all();
unset($aParams['id'], $aParams['_method']);
foreach ($aParams as $k => &$v) {
if (empty($v) && empty($oThisModel->{$k})) {
continue;
}
if (empty($v) && $v !== 0 && $v !== '0') {
$v = '';
}
if ($oThisModel->{$k} != $v) {
$oThisModel->{$k} = $v;
}
}
$oThisModel->save();
$aChangeField = $oThisModel->getChanges();
/// 排除update_at
$sClassName = get_class($this->oModel);
if (
defined($sClassName . '::UPDATED_AT')
&& ($sUpdateColumn = constant($sClassName . '::UPDATED_AT'))
&& !isset($aParams[$sUpdateColumn])
&& isset($aChangeField[$sUpdateColumn])
) {
unset($aChangeField[$sUpdateColumn]);
}
/// 构造msg
$sMsg = "";
$sJiantou = " -> ";
foreach ($aChangeField as $k => $v) {
if (mb_strlen($v, 'UTF-8') > 60 ) {
$sJiantou = '';
// $v = mb_substr($v, 0, 60, 'UTF-8');
$v = '';
}
if (!isset($aParams[$k])) {
$sMsg .= "⚠️ ".$k . $sJiantou . $v . "<br><br>";
} else {
$sMsg .= "".$k . $sJiantou . $v . "<br><br>";
unset($aParams[$k]);
}
}
foreach ($aParams as $k => $v) {
if (mb_strlen($v, 'UTF-8') > 60 ) {
$sJiantou = '';
// $v = mb_substr($v, 0, 60, 'UTF-8');
$v = '';
}
$sMsg .= "".$k . $sJiantou . $v . "<br><br>";
}
$sMsg = rtrim($sMsg, "<br><br>");
return response()->json([
'iCode' => 200,
'aData' => $aChangeField,
'sMsg' => $sMsg
], 200);
}
public function index(Request $oRequest)
{
if (! $this->oModel) {
return response()->json(['code' => 500, 'msg' => '未绑定核心领域模型'], 500);
}
$oQuery = $this->oModel->newQuery();
$aParams = $oRequest->all();
foreach ($aParams as $k => $v) {
if (!empty($this->aFilterFields)) {
if (!in_array($k, $this->aFilterFields)) {
continue;
}
}
// w__name__eq=1
$aK = explode("__", $k);
$sType = $aK[0] ?? '';
$sField = $aK[1] ?? '';
$sOperator = $aK[2] ?? $this->sOperatorDefault;
$sSqlOperator = $this->mapOperator($sOperator);
if (!isset($this->aFilterParams[$sType])) {
continue;
}
if (!$sType || !$sField) {
continue;
}
$this->aFilterParams[$k] = $v;
if ($sType === 'ob') {
$this->aFilterParams[$sType][] = [
'sField' => $sField,
'sSort' => $v ?? $this->sSortDefault
];
continue;
}
if ($sType === 'c') { // 预制条件,字典式
$this->aFilterParams[$sType][$sField] = [
'sOperator' => $sOperator,
'sValue' => $v
];
}
if ($sType === 'cc') { // 自定义条件,集合式
$this->aFilterParams[$sType][] = [
'sField' => $sField,
'sOperator' => $sOperator,
'sValue' => $v
];
}
if (blank($v)) continue; // 空v可以back但不加入sql查询
$sSqlValue = $v;
if ($sSqlOperator === 'like') {
$sSqlValue = "%{$v}%";
}
if (in_array($sField, $this->aDateFields)) {
$oQuery->whereDate($sField, $sSqlOperator, $sSqlValue);
} else {
$oQuery->where($sField, $sSqlOperator, $sSqlValue);
}
}
$iLimit = (int) $oRequest->input('limit', $this->iLimit);
$iLimit = max(1, $iLimit);
$iLimit = min($this->iLimitMax, $iLimit);
if (!empty($this->aFilterParams['ob'])) {
$this->aOrderBy = $this->aFilterParams['ob'];
}
foreach ($this->aOrderBy as $aOrderBy) {
$oQuery->orderBy($aOrderBy['sField'], $aOrderBy['sSort']);
}
$oPaginatedData = $oQuery->paginate($iLimit, array_keys($this->aListFields));
return response()->json([
'iCode' => 200,
'aData' => [
'cList' => $oPaginatedData->items(),
'aListField' => $this->getListFields(),
'aFieldTypes' => $this->aFieldTypes,
'aMap' => $this->oModel->getMapAll(),
'aValueStyle' => $this->aValueStyle,
'aSelectField' => $this->aSelectFields,
'aFilterParam' => $this->aFilterParams,
'aCcField' => $this->aCcFields,
'sCcLast' => $this->getCcLast(),
'sPageName' => $this->sPageName,
'aPager' => [
'aOrderBySchema'=> $this->getOrderBySchema(),
'aOrderBy' => $this->getOrderBy(),
'iTotal' => $oPaginatedData->total(),
'iLimit' => min($this->iLimitMax, $iLimit),
'iCurrentPage' => $oPaginatedData->currentPage(),
'iLastPage' => $oPaginatedData->lastPage(),
'iPerPage' => $oPaginatedData->perPage(),
'iPrevPage' => max(1, $oPaginatedData->currentPage() - 1),
'iNextPage' => min($oPaginatedData->lastPage(), $oPaginatedData->currentPage() + 1)
]
]
], 200);
}
}

View File

@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api\Nasa\V1;
use Illuminate\Http\Request;
use App\Http\Controllers\Api\Nasa\V1\Base\ListController;
final class SettingNavController extends ListController
{
protected string $sModelName = 'Navigation';
protected array $aFilterFields = [ // 允许where的字段不设视为全允许
// 's_name',
// 'i_status'
];
protected string $sPageName = "导航";
protected array $aListFields = [ // list展示的字段和名字映射
'id' => 'id',
'iParentId' => 'pid',
'sName' => 'name',
'sPermissionSlug' => '真slug',
'sComponentType' => '菜单类型',
'sGroup' => 'group',
'sIcon' => 'icon',
'iSort' => 'sort',
'iStatus' => '状态',
'sTestArticle' => '测试article',
'sTestJson' => '测试json',
'dtUpdatedAt'=> '更新时间',
];
protected array $aValueStyle = [ // 特定文字渲染样式
'关闭' => "<span class='text-danger'>关闭</span>",
'开启' => "<span class='text-success'>开启</span>"
];
protected array $aFieldTypes = [
'sTestArticle' => 'article',
'sTestJson' => 'json'
];
protected array $aOrderBy = [
[
"sField" => "id",
"sSort" => "desc",
],
[
"sField" => "iStatus",
"sSort" => "desc",
]
];
protected array $aJsonFields = [ // json字段
];
protected array $aDateFields = [ // date字段
'dtUpdatedAt'
];
protected array $aLenthFields = [ // 限制长度的字段
// "xx" => 100,
];
protected array $aSelectFields = [ // 作为默认select的字段
'iStatus',
'sComponentType',
];
// protected array $aValueFields = [ // 值映射
// 'sComponentType' => [
// 'TOP_BAR' => '顶级菜单',
// 'SIDEBAR_MENU' => '次级菜单',
// 'INNER_PAGE_TAB' => '页内菜单',
// ]
// ];
protected array $aCcExtFields = [
'dtCreatedAt' => '创建时间'
];
// protected array $aLimit = [3, 15, 40, 100]; // list长度第一个为默认
}
//CREATE TABLE `nasa_navigation` (
// `iId` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
// `iParentId` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '父级ID0代表顶级导航',
// `sName` varchar(64) NOT NULL COMMENT '导航菜单名称',
// `sSlug` varchar(128) NOT NULL DEFAULT '' COMMENT 'Laravel 路由别名(Route Name)',
// `sIcon` varchar(64) NOT NULL DEFAULT '' COMMENT '图标 Class/Svg 标识',
// `sGroup` varchar(128) NOT NULL DEFAULT '',
// `sComponentType` varchar(32) NOT NULL DEFAULT 'SIDEBAR_MENU' COMMENT '渲染组件类型TOP_BAR, SIDEBAR_MENU, INNER_PAGE_TAB',
// `iSort` int(11) NOT NULL DEFAULT 0 COMMENT '排序权重(数值越小越靠前)',
// `iStatus` tinyint(4) NOT NULL DEFAULT 1 COMMENT '是否可见1-显示, 0-隐藏',
// `sPermissionSlug` varchar(64) DEFAULT NULL COMMENT '权限标识(用于中间件拦截校验)',
// `dtCreatedAt` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '创建时间',
// `dtUpdatedAt` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() COMMENT '更新时间',
// PRIMARY KEY (`iId`),
// KEY `idx_status_parent_sort` (`iStatus`,`iParentId`,`iSort`),
// KEY `idx_permission` (`sPermissionSlug`)
//) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统功能导航路由表';

View File

@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\ArticleList;
use App\Services\Time;
use voku\helper\AntiXSS;
use App\Models\Tags;
use App\Services\TomTool\Http;
class NimaController
{
public function index()
{
return view("pages.dashboard", []);
}
}

View File

@ -0,0 +1,66 @@
<?php
namespace App\Http\Controllers\Web;
use App\Models\Bird;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\View\View;
class BirdController
{
/**
* 显示鸟类档案列表(大厂工业规范版)
* 谐音发音:因代克斯 (Index) -> 意为索引、列表
*/
public function index(): \Illuminate\View\View
{
// 工业标准:按创建时间倒序排列,每页严格限制 10 条数据
// 匈牙利命名法c前缀代表集合(Collection)
$cBirdList = \App\Models\Bird::latest()->paginate(10);
// 渲染列表模板,把数据送过去
return view('bird.index', compact('cBirdList'));
}
/**
* 1. 显示新建鸟类档案的界面
*/
public function create(): View
{
return view('bird.create');
}
/**
* 2. 保存鸟类数据 (就是你刚才弄好的那个方法,保持原样)
*/
public function store(Request $oRequest): JsonResponse
{
$aValidated = $oRequest->validate([
'title' => 'required|string|max:255',
'markdown_content' => 'required|string',
]);
$oBird = Bird::create($aValidated);
return response()->json([
'status' => 'success',
'data' => [
'id' => $oBird->id
]
], 201);
}
/**
* 3. 显示鸟类档案详情界面(演示渲染出来的 Markdown
*/
public function show(int $iId): View
{
// 遵循大厂防御性编程:找不到直接抛出 404
// 谐音发音:凡得 欧尔 飞儿 (Find or Fail)
$oBird = Bird::findOrFail($iId);
// 传给 Blade 模板
return view('bird.show', compact('oBird'));
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace App\Http\Controllers\Web\Nasa\V1;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\RedirectResponse;
use App\Models\Users;
class AuthController
{
public function login()
{
return view('nasa.v1.auth.login');
}
public function in(Request $oRequest)
{
$oRequest->validate([
'sUserName' => 'required|string|min:2|max:50',
'sPwd' => 'required|string|min:3',
]);
$sUserName = $oRequest->input("sUserName");
$sPwd = $oRequest->input("sPwd");
$sPwd = md5($sPwd."-kof98");
$oUser = Users::where("name", $sUserName)->where("password", $sPwd)->first();
if (!$oUser) {
return response()->json([
'iCode' => 201,
'sMessage' => '账号或密码错误',
'aData' => null
], 201);
}
Auth::login($oUser);
$oRequest->session()->regenerate();
$aDataResult = [
'iCode' => 200,
'sMessage' => '登录成功',
'aData' => [
'iUserId' => $oUser->id,
'sUserName' => $oUser->name,
]
];
return response()->json($aDataResult, 200);
}
public function out(Request $oRequest): RedirectResponse
{
Auth::logout();
$oRequest->session()->invalidate();
$oRequest->session()->regenerateToken();
return redirect('/nasa/login');
}
}

View File

@ -0,0 +1,120 @@
<?php
namespace App\Http\Controllers\Web\Nasa\V1\Base;
use Illuminate\Http\Request;
use App\Http\Requests\Nasa\NasaQueryRequest;
use Illuminate\View\View;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Arr;
class ListController
{
protected string $sApiPath = '';
protected string $sView = 'nasa._commons.list';
protected string $sSiteWww = '';
protected string $sHeaderActionView = 'nasa.v1._actions.list';
public function index(NasaQueryRequest $oRequest): View
{
$aCleanQuery = $oRequest->cleanQuery();
$oResponse = Http::nasa($this->sSiteWww)->get($this->sApiPath, $aCleanQuery);
$aResponse = $oResponse->json();
$aResponse['sApiPath'] = $this->sApiPath;
$aResponse['sSiteWww'] = $this->sSiteWww;
$aResponse['sHeaderActionView'] = $this->sHeaderActionView;
return view($this->sView, $aResponse);
}
public function detail(NasaQueryRequest $oRequest): View
{
$iId = intval(request('id'));
$sApiPath = $oRequest->input('api_path');
$sSiteWww = $oRequest->input('site_www');
$oResponse = Http::nasa($sSiteWww)->get($sApiPath.'/detail/' . $iId);
return view('nasa._commons.detail', $oResponse->json());
}
public function detailSave(NasaQueryRequest $oRequest)
{
$iId = intval(request('id'));
$aParams = $oRequest->all() ?? [];
$sApiPath = Arr::pull($aParams, 'api_path');
$sSiteWww = Arr::pull($aParams, 'site_www');
$oResponse = Http::nasa($sSiteWww)->put($sApiPath.'/detail/' . $iId, $aParams);
return response()->json($oResponse->json(), 200);
}
public function delete(NasaQueryRequest $oRequest)
{
$iId = intval(request('id'));
$aParams = $oRequest->all() ?? [];
$sApiPath = Arr::pull($aParams, 'api_path');
$sSiteWww = Arr::pull($aParams, 'site_www');
$oResponse = Http::nasa($sSiteWww)->delete($sApiPath.'/delete/' . $iId);
return response()->json($oResponse->json(), 200);
}
public function add(NasaQueryRequest $oRequest)
{
$sApiPath = $oRequest->input('api_path');
$sSiteWww = $oRequest->input('site_www');
$oResponse = Http::nasa($sSiteWww)->get($sApiPath.'/add');
return view('nasa._commons.add', $oResponse->json());
}
public function addSave(NasaQueryRequest $oRequest)
{
$aParams = $oRequest->all() ?? [];
$sApiPath = Arr::pull($aParams, 'api_path');
$sSiteWww = Arr::pull($aParams, 'site_www');
$oResponse = Http::nasa($sSiteWww)->put($sApiPath.'/add', $aParams);
return response()->json($oResponse->json());
}
public function clone(NasaQueryRequest $oRequest): View
{
$iId = intval(request('id'));
$sApiPath = $oRequest->input('api_path');
$sSiteWww = $oRequest->input('site_www');
$oResponse = Http::nasa($sSiteWww)->get($sApiPath.'/clone/' . $iId);
return view('nasa._commons.clone', $aResponse = $oResponse->json());
}
public function cloneSave(NasaQueryRequest $oRequest)
{
$aParams = $oRequest->all() ?? [];
$sApiPath = Arr::pull($aParams, 'api_path');
$sSiteWww = Arr::pull($aParams, 'site_www');
$oResponse = Http::nasa($sSiteWww)->put($sApiPath.'/add', $aParams);
return response()->json($oResponse->json());
}
public function hit(NasaQueryRequest $oRequest)
{
$iId = intval(request('id'));
$sApiPath = $oRequest->input('api_path');
$sSiteWww = $oRequest->input('site_www');
$sField = request('field');
$oResponse = Http::nasa($sSiteWww)->get($sApiPath.'/hit/' . $iId . '/' . $sField);
return response()->json($oResponse->json(), 200);
}
}

View File

@ -0,0 +1,110 @@
<?php
namespace App\Http\Controllers\Web\Nasa\V1\Demo;
use Illuminate\Http\Request;
use Illuminate\View\View;
class NasaStyleController
{
public function dashboard()
{
return view('nasa.v1.demo.nasa.style.dashboard');
}
public function rbac()
{
return view('nasa.v1.demo.nasa.style.rbac');
}
public function topology()
{
return view('nasa.v1.demo.nasa.style.topology');
}
public function config()
{
return view('nasa.v1.demo.nasa.style.config');
}
public function getway()
{
return view('nasa.v1.demo.nasa.style.getway');
}
public function rsa()
{
return view('nasa.v1.demo.nasa.style.rsa');
}
public function finder()
{
return view('nasa.v1.demo.nasa.style.finder');
}
public function disaster()
{
return view('nasa.v1.demo.nasa.style.disaster');
}
public function cache()
{
return view('nasa.v1.demo.nasa.style.cache');
}
public function cron()
{
return view('nasa.v1.demo.nasa.style.cron');
}
public function kafka()
{
return view('nasa.v1.demo.nasa.style.kafka');
}
public function topology2()
{
return view('nasa.v1.demo.nasa.style.topology2');
}
public function shifter()
{
return view('nasa.v1.demo.nasa.style.shifter');
}
public function download()
{
return view('nasa.v1.demo.nasa.style.download');
}
public function tuning()
{
return view('nasa.v1.demo.nasa.style.tuning');
}
public function sandbox()
{
return view('nasa.v1.demo.nasa.style.sandbox');
}
public function interlock()
{
return view('nasa.v1.demo.nasa.style.interlock');
}
public function list()
{
return view('nasa.v1.demo.nasa.style.list');
}
public function botton()
{
return view('nasa.v1.demo.nasa.style.botton');
}
public function botton2()
{
return view('nasa.v1.demo.nasa.style.botton2');
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Http\Controllers\Web\Nasa\V1\Node;
use Illuminate\Http\Request;
use App\Http\Requests\Nasa\NasaQueryRequest;
use Illuminate\View\View;
use Illuminate\Support\Facades\Http;
use App\Http\Controllers\Web\Nasa\V1\Base\ListController;
class FuNodeController extends ListController
{
protected string $sApiPath = 'node';
protected string $sView = 'nasa._commons.list';
protected string $sSiteWww;
protected string $sHeaderActionView = 'nasa.v1._actions.list';
public function __construct()
{
$this->sSiteWww = config("path.url_ship_fu_base") ?? '';
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Http\Controllers\Web\Nasa\V1\Setting;
use Illuminate\Http\Request;
use App\Http\Requests\Nasa\NasaQueryRequest;
use Illuminate\View\View;
use Illuminate\Support\Facades\Http;
use App\Http\Controllers\Web\Nasa\V1\Base\ListController;
class MasterNavController extends ListController
{
protected string $sApiPath = "setting/nav";
protected string $sView = 'nasa._commons.list';
protected string $sSiteWww;
protected string $sHeaderActionView = 'nasa.v1._actions.nav';
public function __construct()
{
$this->sSiteWww = config("path.url_master_base") ?? '';
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace App\Http\Controllers\Web\Nasa\V1\Stats;
use Illuminate\Http\Request;
use Illuminate\View\View;
class DashboardTotalController
{
public function index()
{
return view('nasa.v1.stats.dashboard.total');
}
// protected HomeNavService $oNavService;
//
// public function __construct(HomeNavService $oNavService)
// {
// $this->oNavService = $oNavService;
// }
//
// /**
// * 业务方法看好了Controller 里面变得极度纯粹!
// */
// public function oShowTrafficConfig(Request $oRequest): View
// {
// $sCurrentSlug = $oRequest->route()->getName();
//
// // 控制器只抓属于当前业务页面名下的页内 Tab剩下的全局导航它一概不理
// $cPageTabs = $this->oNavService->cGetPageTabs($sCurrentSlug);
//
// return view('home.traffic.config', [
// 'cPageTabs' => $cPageTabs,
// ]);
// }
}

View File

@ -1,21 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
//use voku\helper\AntiXSS;
class Test
{
public function handle(Request $request, Closure $next): Response
{
$sSearch = request('search');
// echo $sSearch;exit;
return $next($request);
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Facades\Log;
/**
* 🚀 NASA 核心网关Header 签名安全卫士
* 🗣️ Verify 发音:/ˈverɪfaɪ/ 维瑞发一 ,意为:校验、证实
*/
final class VerifyNasaToken
{
public function handle(Request $oRequest, Closure $fNext): Response
{
// 👑 大厂全线对接:丢掉 $oRequest->input(),全面改用 ->header() 降维打击!
// 🎯 核心微操Laravel 的 header() 方法天生自带防抖,它对大小写不敏感,
// 你传 'X-Nasa-Token' 或者 'x-nasa-token',底层都能稳稳咬住!
$iRequestTime = (int)$oRequest->header('X-Nasa-Timestamp');
$sClientToken = $oRequest->header('X-Nasa-Token');
// 1. 钢铁防御线一:前置空值熔断,连参数都没有的盲流直接当场轰杀
if (!$iRequestTime || !$sClientToken) {
return response()->json(['iStatus' => 0, 'sMsg' => 'Security Headers Missing'], 403);
}
// 2. 时效性防御:前后端时间差超过 60 秒判定为重放攻击或过期
if (abs(time() - $iRequestTime) > 60) {
Log::warning("🛰️ NASA 网关拦截:请求超时已过期!当前服务器时间: " . time() . ",请求时间: {$iRequestTime}");
return response()->json(['iStatus' => 0, 'sMsg' => 'Request Expired'], 403);
}
// 3. 验签防御:从配置核心仓掏出密钥,用相同算法重算 Token 对比
$sLocalSecret = config('nasa.secret');
$sExpectedToken = md5("timestamp={$iRequestTime}&secret={$sLocalSecret}");
// 4. 钢铁防御线二:像素级对撞签名
if ($sClientToken !== $sExpectedToken) {
Log::error("🚨 NASA 网关警报:发现非法伪造签名!客户端传值: {$sClientToken},期望值: {$sExpectedToken}");
return response()->json(['iStatus' => 0, 'sMsg' => 'Invalid Token'], 403);
}
// 5. 安全放行,通电!
return $fNext($oRequest);
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace App\Http\Requests\Nasa;
use Illuminate\Foundation\Http\FormRequest;
class NasaQueryRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
//
];
}
public function cleanQuery(): array
{
// 🧬 利用 Laravel 11 极其强大的 collect 简化闭环
return collect($this->query())->transform(function ($xValue) {
return is_null($xValue) ? '' : $xValue;
})->all();
}
}

42
app/Models/Bird.php Normal file
View File

@ -0,0 +1,42 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Attribute;
use League\CommonMark\GithubFlavoredMarkdownConverter;
class Bird extends Model
{
// 显式指定表名
protected $table = 'birds';
// 批量赋值白名单
protected $fillable = ['title', 'markdown_content'];
/**
* 工业级设计:只读的虚拟属性 html_content
* 自动转换并过滤 XSS
*/
protected function htmlContent(): Attribute
{
return Attribute::make(
get: function () {
// 匈牙利命名法s前缀表示字符串
$sMarkdown = $this->attributes['markdown_content'] ?? '';
if (empty($sMarkdown)) {
return '';
}
// 实例化大厂标准的 GitHub Markdown 转换器
// 谐音发音:看沃特尔 (Con-vert-er)
$oConverter = new GithubFlavoredMarkdownConverter([
'html_input' => 'strip', // 安全核心:剥离所有原生 HTML 标签,彻底防御 XSS
'allow_unsafe_links' => false, // 禁用 javascript: 等不安全协议链接
]);
return $oConverter->convert($sMarkdown)->getContent();
}
);
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace App\Models\Nasa;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Route;
class Navigation extends Model
{
protected $table = 'nasa_navigation';
protected $primaryKey = 'id';
const CREATED_AT = 'dtCreatedAt';
const UPDATED_AT = 'dtUpdatedAt';
const TYPE_TOP_BAR = 'TOP_BAR';
const TYPE_SIDEBAR_MENU = 'SIDEBAR_MENU';
const TYPE_INNER_PAGE_TAB = 'INNER_PAGE_TAB';
const STATUS_OPEN = 1;
const STATUS_CLOSE = 0;
private static array $aComponentLabels = [
self::TYPE_TOP_BAR => '顶部导航条',
self::TYPE_SIDEBAR_MENU => '侧边栏菜单',
self::TYPE_INNER_PAGE_TAB => '页面内标签页',
];
private static array $aStatusLabels = [
self::STATUS_OPEN => '开启',
self::STATUS_CLOSE => '关闭',
];
public function getMapAll()
{
$aMap = [
'sComponentType' => self::$aComponentLabels,
'iStatus' => self::$aStatusLabels
];
return $aMap;
}
protected function casts(): array
{
return [
'dtUpdatedAt' => 'datetime:Y-m-d H:i:s', // 自动转换为 Carbon 对象
'dtCreatedAt' => 'datetime:Y-m-d H:i:s', // 写入时自动 password_hash 加密
];
}
/**
* 递归获取当前菜单的所有上级祖先节点(包含自身)
* 结果按从根节点到当前节点的顺序排列(即:[一级, 二级, 三级, 当前]
*
* @return \Illuminate\Support\Collection
*/
public function cGetAncestorsAndSelf(): \Illuminate\Support\Collection
{
$cPath = collect([$this]);
$oCurrent = $this;
// 使用循环代替递归进行反向溯源,性能更佳,防止极端情况下的堆栈溢出
while ($oCurrent->iParentId != 0) {
// 高标准注意:这里如果能做内存缓存或走预加载更佳,但由于是单条数据向上,走主键查询性能损耗可控
$oParent = self::where('id', $oCurrent->iParentId)->available()->first();
if (!$oParent) {
break; // 防御性编程:万一数据链断了,及时跳出
}
$cPath->prepend($oParent); // 往前插入,保证顺序是 [父, 子, 孙]
$oCurrent = $oParent;
}
return $cPath;
}
public function children()
{
// 这里的 iParentId 是外键id 是当前表的主键
return $this->hasMany(self::class, 'iParentId', 'id');
}
/**
* 你的本地作用域Scope确保 scopeAvailable 存在
* 顺便提一句,高标准设计中,状态字段建议内聚在 scope
*/
public function scopeAvailable($query)
{
// 假设你的可用状态字段是 iStatus 且 1 为可用,请根据实际字段调整
return $query->where('iStatus', 1);
}
/**
* 高标准设计:递归预加载所有下级(无限级核心)
* 只要这一条 Eager LoadingLaravel 会自动用最少的 SQL 把整棵树一次性读入内存
*/
public function childrenRecursive()
{
return $this->children()
->available()
->orderBy('iSort', 'asc')
->with('childrenRecursive'); // 完美的自我套娃
}
/**
* 业务逻辑内聚:深度优先穿透获取最终 URL
* 职责:如果有下级,永远优先往下找第一个合法的下级;如果没有下级或下级全挂了,退回自身。
*/
public function sGetFinalUrl(): string
{
// 1. 如果有下级集合(已经过 available 过滤),尝试向下穿透
if ($this->relationLoaded('childrenRecursive') && $this->childrenRecursive->isNotEmpty()) {
foreach ($this->childrenRecursive as $oChild) {
// 递归向下寻找子节点的最终 URL
$sChildUrl = $oChild->sGetFinalUrl();
// 只要子节点或者孙子节点能返回一个有效 URL立刻中断并返回它最左原则
if (!empty($sChildUrl)) {
return $sChildUrl;
}
}
}
// 2. 兜底逻辑:没有下级,或者所有下级分支都没配置有效路由,返回自身的 URL
return Route::has($this->sPermissionSlug) ? route($this->sPermissionSlug) : '';
}
}

35
app/Models/Users.php Executable file
View File

@ -0,0 +1,35 @@
<?php
namespace App\Models;
// 🚨 注意看:大厂规范,必须引入这个专门用于认证的基类,而不是普通的 Model
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
/**
* Class Users
* @package App\Models
*/
class Users extends Authenticatable // 💎 核心:这里改成继承 Authenticatable而不是 Model
{
use Notifiable;
// 如果你的表名就是 users可以不写如果是别的在这里指定
protected $table = 'users';
/**
* 大厂规范:定义允许批量赋值的白名单字段
*/
protected $fillable = [
'name',
'password',
];
/**
* 大厂规范:敏感字段在序列化成数组或 JSON 时必须隐藏,防止泄露!
*/
protected $hidden = [
'password',
'remember_token',
];
}

View File

@ -2,23 +2,64 @@
namespace App\Providers;
use App\Services\Nasa\NavigationService as NasaNavService;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\View;
use Illuminate\Http\Request;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
public function register(): void {}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
Request::macro('fullUrlWithAllQuery', function (array $aNewQuery = []) {
$aCleanQuery = collect($this->query())
->transform(fn($xV) => is_null($xV) ? '' : $xV)
->merge($aNewQuery)
->all();
return $this->url() . '?' . http_build_query($aCleanQuery);
});
Http::macro('nasa', function (string $sSiteWww, string $sVersion = 'v1') {
$iTimestamp = time();
$sSecret = config('nasa.key');
$sToken = md5("timestamp={$iTimestamp}&secret={$sSecret}");
$bVerifySsl = config('nasa.verify_ssl');
if (env('is_loc') == true) {
$h = "http";
} else {
$h = "https";
}
return Http::baseUrl($h."://" . $sSiteWww . "/api/nasa/{$sVersion}")
->acceptJson()
->timeout(10)
->throw()
->withHeaders([
'X-Nasa-Timestamp' => $iTimestamp,
'X-Nasa-Token' => $sToken,
])
->withOptions([
'verify' => $bVerifySsl,
// 'debug' => true
]);
});
View::composer('components.layouts.nasa.app', function ($oView) {
$oNavService = app(NasaNavService::class);
$sCurrentPermissionSlug = request()->route() ? request()->route()->getName() : '';
$aNavInfo = $oNavService->aGetInfo($sCurrentPermissionSlug);
//tt($aNavInfo);
$aWith = [
"aNavInfo" => $aNavInfo
];
$oView->with($aWith);
});
}
}

View File

@ -0,0 +1,134 @@
<?php
namespace App\Services\Nasa;
use App\Models\Nasa\Navigation as NasaNavigation;
use Illuminate\Support\Collection;
class NavigationService
{
public function aGetInfo($sCurrentPermissionSlug): array
{
// 1. 获取当前高亮的菜单节点
$oCurrentMenu = NasaNavigation::where("sPermissionSlug", $sCurrentPermissionSlug)
->available()
->first();
if (!$oCurrentMenu) {
return [
"aTopMenus" => $this->aGetTopMenus(),
"aSubMenus" => [],
"aTabMenus" => [],
"aMenuPath" => [],
];
}
$aTopMenus = $this->aGetTopMenus();
// 2. 获取面包屑的原始集合(链条顺序依然是:[一级, 二级, 三级...]
$cMenuPathCollection = $oCurrentMenu->cGetAncestorsAndSelf();
// ================= 核心修改:利用 keyBy 将 sComponentType 作为键 =================
// 它会自动将数组转换为:['TOP_BAR' => [...], 'LEFT_MENU' => [...]] 的高内聚结构
$aMenuPath = $cMenuPathCollection->keyBy('sComponentType')->toArray();
// ==============================================================================
// 3. 提取一级根节点(注意:集合 keyBy 后内部指针会变,所以我们从原集合中安全 get(0) 获取一级)
$oRootMenu = $cMenuPathCollection->first();
$aSubMenus = [];
$aTabMenus = [];
if ($oRootMenu) {
// 拉出该顶级菜单下的所有无限级子树
$oRootMenuWithTree = NasaNavigation::with('childrenRecursive')
->where('id', $oRootMenu->id)
->first();
if ($oRootMenuWithTree && $oRootMenuWithTree->childrenRecursive) {
// 【二级侧边栏逻辑】:保持原样
$aSubMenus = $oRootMenuWithTree->childrenRecursive
->transform(function (NasaNavigation $oSubMenu) {
$oSubMenu->sUrl = $oSubMenu->sGetFinalUrl();
return $oSubMenu;
})
->groupBy('sGroup')
->toArray();
// ================= 三级 Tab 菜单解析优化 =================
// 以前是通过 ->get(1) 硬编码拿二级。现在既然改了结构,
// 我们可以直接通过你定义的二级类型键(假设叫 TYPE_SIDE_BAR请根据你 Model 里的常量自行替换)安全捞取
$oLevel2Menu = $cMenuPathCollection->firstWhere('sComponentType', NasaNavigation::TYPE_SIDEBAR_MENU);
if ($oLevel2Menu) {
// 去子树内存里捞出这个二级节点
$oCurrentLevel2InTree = $oRootMenuWithTree->childrenRecursive
->firstWhere('id', $oLevel2Menu->id);
if ($oCurrentLevel2InTree && $oCurrentLevel2InTree->childrenRecursive->isNotEmpty()) {
$aTabMenus = $oCurrentLevel2InTree->childrenRecursive
->transform(function (NasaNavigation $oTabMenu) {
$oTabMenu->sUrl = $oTabMenu->sGetFinalUrl();
return $oTabMenu;
})
->toArray();
}
}
}
}
return [
"aTopMenus" => $aTopMenus,
"aSubMenus" => $aSubMenus,
"aTabMenus" => $aTabMenus,
"aMenuPath" => $aMenuPath, // 这里的键已经是你的组件类型字符串了
];
}
/**
* 获取全局顶级大区 (TOP_BAR)
*/
public function aGetTopMenus(): array
{
return NasaNavigation::with('childrenRecursive') // 一口气拉出无限级树结构,只有 2-3 条 SQL
->where('iParentId', 0)
->where('sComponentType', NasaNavigation::TYPE_TOP_BAR)
->available()
->orderBy('iSort', 'asc')
->get()
->transform(function (NasaNavigation $oMenu) {
// 让顶级菜单自己去递归嗅探最底层的有效 URL
$oMenu->sUrl = $oMenu->sGetFinalUrl();
return $oMenu;
})
->groupBy('sGroup')
->toArray();
}
/**
* 抓取侧边栏业务菜单树
*/
public function aGetSubMenus($iParentId): Array
{
return NasaNavigation::where('iParentId', $iParentId)
->where('sComponentType', NasaNavigation::TYPE_SIDEBAR_MENU)
->available()
->orderBy('iSort', 'asc')
->get()
->map(function ($oMenu) {
// 将模型转成数组
$aMenu = $oMenu->toArray();
// 🎯 核心防空伞:动态算好 sUrl有就给没有就给空字符串 ''
$aMenu['sUrl'] = \Illuminate\Support\Facades\Route::has($oMenu->sPermissionSlug)
? route($oMenu->sPermissionSlug)
: '';
return $aMenu;
})
->groupBy('sGroup')
->toArray();
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace App\Services\Nasa;
use App\Models\Nasa\Navigation as NasaNavigation;
class NavigationService
{
/**
* 获取全通用无限级菜单及当前激活上下文
*/
public function aGetInfo(string $sCurrentPermissionSlug): array
{
// 1. 抓取当前激活的节点
$oCurrentMenu = NasaNavigation::where("sPermissionSlug", $sCurrentPermissionSlug)
->available()
->first();
// 2. 空白防御:如果路由不存在于菜单配置中,仅渲染全局根树
if (!$oCurrentMenu) {
return [
"aMenuTree" => $this->aGetGlobalTree(),
"aMenuPath" => [],
];
}
// 3. 计算面包屑/溯源链 (链条顺序:[一级, 二级, 三级...])
$cMenuPathCollection = $oCurrentMenu->cGetAncestorsAndSelf();
// 保持匈牙利命名法及纯数组输出,用 iId 或 sPermissionSlug 作为键,彻底停用组件类型做键
$aMenuPath = $cMenuPathCollection->keyBy('iId')->toArray();
// 4. 获取完整的全局树(包含各级孩子节点)
$aMenuTree = $this->aGetGlobalTree();
return [
"aMenuTree" => $aMenuTree, // 全量的无限级树状数据,交由前端去递归渲染或按层级拆解
"aMenuPath" => $aMenuPath, // 当前激活的整条链路,前端用来做多级高亮匹配
];
}
/**
* 抓取完整的全局无限级菜单树 (支持无限层级拓展)
*/
public function aGetGlobalTree(): array
{
return NasaNavigation::with('childrenRecursive')
->where('iParentId', 0) // 从最顶层根节点开始往下拉
->available()
->orderBy('iSort', 'asc')
->get()
->map(function (NasaNavigation $oMenu) {
return $this->aFormatMenuNode($oMenu);
})
->toArray();
}
/**
* 内部递归格式化节点:解耦并动态计算每一个节点的最终有效 URL
*/
private function aFormatMenuNode(NasaNavigation $oMenu): array
{
// 将当前模型转为基础数组
$aMenu = $oMenu->toArray();
// 动态计算 URL 职责收拢
$aMenu['sUrl'] = $oMenu->sGetFinalUrl();
// 核心:如果存在递归子集,递归往下格式化,实现无限级兼容
if ($oMenu->relationLoaded('childrenRecursive') && $oMenu->childrenRecursive->isNotEmpty()) {
$aMenu['children_recursive'] = $oMenu->childrenRecursive
->map(function (NasaNavigation $oChildMenu) {
return $this->aFormatMenuNode($oChildMenu);
})
->toArray();
}
return $aMenu;
}
}

View File

@ -7,12 +7,13 @@ use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
//'test' => \App\Http\Middleware\Test::class,
'nasa.auth' => \App\Http\Middleware\VerifyNasaToken::class,
]);
$middleware->validateCsrfTokens(except: [
'api/*',
@ -20,5 +21,21 @@ return Application::configure(basePath: dirname(__DIR__))
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
// 🌟 战略监控:只要全站任何地方发生 cURL 崩溃,这里统一抓获
$exceptions->render(function (\Illuminate\Http\Client\RequestException $e) {
// $a = [
// 'sUrl' => $e->response->effectiveUri(),
// 'iCode' => $e->response->status(),
// 'sBody' => $e->response->body(),
// ];
return response()->json([
'iCode' => $e->response->status(),
'aData' => $e->response->body()
], $e->response->status());
// echo "<pre>";
// var_dump($a);
// exit;
});
})->create();

View File

@ -11,7 +11,9 @@
"intervention/image": "^3.11",
"irazasyed/telegram-bot-sdk": "^3.15",
"laravel/framework": "^11.31",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9",
"league/commonmark": "^2.8",
"symfony/yaml": "^7.4",
"voku/anti-xss": "^4.1"
},

85
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "60674f80fc8b7a52ce2d729648d5b538",
"content-hash": "6d33a9af7883a91f1b6c86abbd6a7d5e",
"packages": [
{
"name": "brick/math",
@ -1555,6 +1555,69 @@
},
"time": "2024-11-12T14:59:47+00:00"
},
{
"name": "laravel/sanctum",
"version": "v4.3.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/sanctum.git",
"reference": "2a9bccc18e9907808e0018dd15fa643937886b1e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/sanctum/zipball/2a9bccc18e9907808e0018dd15fa643937886b1e",
"reference": "2a9bccc18e9907808e0018dd15fa643937886b1e",
"shasum": ""
},
"require": {
"ext-json": "*",
"illuminate/console": "^11.0|^12.0|^13.0",
"illuminate/contracts": "^11.0|^12.0|^13.0",
"illuminate/database": "^11.0|^12.0|^13.0",
"illuminate/support": "^11.0|^12.0|^13.0",
"php": "^8.2",
"symfony/console": "^7.0|^8.0"
},
"require-dev": {
"mockery/mockery": "^1.6",
"orchestra/testbench": "^9.15|^10.8|^11.0",
"phpstan/phpstan": "^1.10"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Sanctum\\SanctumServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Sanctum\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.",
"keywords": [
"auth",
"laravel",
"sanctum"
],
"support": {
"issues": "https://github.com/laravel/sanctum/issues",
"source": "https://github.com/laravel/sanctum"
},
"time": "2026-04-30T11:46:25+00:00"
},
{
"name": "laravel/serializable-closure",
"version": "v2.0.1",
@ -1684,16 +1747,16 @@
},
{
"name": "league/commonmark",
"version": "2.6.0",
"version": "2.8.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "d150f911e0079e90ae3c106734c93137c184f932"
"reference": "59fb075d2101740c337c7216e3f32b36c204218b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d150f911e0079e90ae3c106734c93137c184f932",
"reference": "d150f911e0079e90ae3c106734c93137c184f932",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/59fb075d2101740c337c7216e3f32b36c204218b",
"reference": "59fb075d2101740c337c7216e3f32b36c204218b",
"shasum": ""
},
"require": {
@ -1718,11 +1781,11 @@
"phpstan/phpstan": "^1.8.2",
"phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0",
"scrutinizer/ocular": "^1.8.1",
"symfony/finder": "^5.3 | ^6.0 | ^7.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
"symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0",
"unleashedtech/php-coding-standard": "^3.1.1",
"vimeo/psalm": "^4.24.0 || ^5.0.0"
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
},
"suggest": {
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
@ -1730,7 +1793,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.7-dev"
"dev-main": "2.9-dev"
}
},
"autoload": {
@ -1787,7 +1850,7 @@
"type": "tidelift"
}
],
"time": "2024-12-07T15:34:16+00:00"
"time": "2026-03-19T13:16:38+00:00"
},
{
"name": "league/config",

View File

@ -62,7 +62,7 @@ return [
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', App\Models\User::class),
'model' => env('AUTH_MODEL', App\Models\Users::class),
],
// 'users' => [

20
config/cors.php Normal file
View File

@ -0,0 +1,20 @@
<?php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie', '*'],
'allowed_methods' => ['*'],
// 💡 核心修正:加入你的本地自定义域名
'allowed_origins' => [
'http://dd.loc',
'http://localhost',
'http://127.0.0.1'
],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];

7
config/nasa.php Executable file
View File

@ -0,0 +1,7 @@
<?php
return [
'secret' => env('NASA_API_SECRET'),
'key' => env('NASA_API_KEY'),
'verify_ssl' => env('NASA_API_VERIFY_SSL', true),
];

View File

@ -1,7 +1,7 @@
<?php
return [
"url_nodehub_base" => env("url_nodehub_base"),
"url_master_base" => env("url_master_base"),
"url_ship_fu_base" => env("url_ship_fu_base"),
];

87
config/sanctum.php Normal file
View File

@ -0,0 +1,87 @@
<?php
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\ValidateCsrfToken;
use Laravel\Sanctum\Http\Middleware\AuthenticateSession;
use Laravel\Sanctum\Sanctum;
return [
/*
|--------------------------------------------------------------------------
| Stateful Domains
|--------------------------------------------------------------------------
|
| Requests from the following domains / hosts will receive stateful API
| authentication cookies. Typically, these should include your local
| and production domains which access your API via a frontend SPA.
|
*/
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
Sanctum::currentApplicationUrlWithPort(),
// Sanctum::currentRequestHost(),
))),
/*
|--------------------------------------------------------------------------
| Sanctum Guards
|--------------------------------------------------------------------------
|
| This array contains the authentication guards that will be checked when
| Sanctum is trying to authenticate a request. If none of these guards
| are able to authenticate the request, Sanctum will use the bearer
| token that's present on an incoming request for authentication.
|
*/
'guard' => ['web'],
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. This will override any values set in the token's
| "expires_at" attribute, but first-party sessions are not affected.
|
*/
'expiration' => null,
/*
|--------------------------------------------------------------------------
| Token Prefix
|--------------------------------------------------------------------------
|
| Sanctum can prefix new tokens in order to take advantage of numerous
| security scanning initiatives maintained by open source platforms
| that notify developers if they commit tokens into repositories.
|
| See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning
|
*/
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
/*
|--------------------------------------------------------------------------
| Sanctum Middleware
|--------------------------------------------------------------------------
|
| When authenticating your first-party SPA with Sanctum you may need to
| customize some of the middleware Sanctum uses while processing the
| request. You may change the middleware listed below as required.
|
*/
'middleware' => [
'authenticate_session' => AuthenticateSession::class,
'encrypt_cookies' => EncryptCookies::class,
'validate_csrf_token' => ValidateCsrfToken::class,
],
];

View File

@ -7,7 +7,7 @@ use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Users>
*/
class UserFactory extends Factory
{

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->text('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable()->index();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};

View File

@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
// 表名按要求为 birds
Schema::create('birds', function (Blueprint $table) {
$table->id();
$table->string('title', 255)->comment('鸟类标题');
$table->text('markdown_content')->comment('Markdown原始文本');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('birds');
}
};

View File

@ -2,7 +2,7 @@
namespace Database\Seeders;
use App\Models\User;
use App\Models\Users;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

20
lang/en/auth.php Normal file
View File

@ -0,0 +1,20 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'These credentials do not match our records.',
'password' => 'The provided password is incorrect.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
];

19
lang/en/pagination.php Normal file
View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Previous',
'next' => 'Next &raquo;',
];

22
lang/en/passwords.php Normal file
View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| outcome such as failure due to an invalid password / reset token.
|
*/
'reset' => 'Your password has been reset.',
'sent' => 'We have emailed your password reset link.',
'throttled' => 'Please wait before retrying.',
'token' => 'This password reset token is invalid.',
'user' => "We can't find a user with that email address.",
];

194
lang/en/validation.php Normal file
View File

@ -0,0 +1,194 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute field must be accepted.',
'accepted_if' => 'The :attribute field must be accepted when :other is :value.',
'active_url' => 'The :attribute field must be a valid URL.',
'after' => 'The :attribute field must be a date after :date.',
'after_or_equal' => 'The :attribute field must be a date after or equal to :date.',
'alpha' => 'The :attribute field must only contain letters.',
'alpha_dash' => 'The :attribute field must only contain letters, numbers, dashes, and underscores.',
'alpha_num' => 'The :attribute field must only contain letters and numbers.',
'array' => 'The :attribute field must be an array.',
'ascii' => 'The :attribute field must only contain single-byte alphanumeric characters and symbols.',
'before' => 'The :attribute field must be a date before :date.',
'before_or_equal' => 'The :attribute field must be a date before or equal to :date.',
'between' => [
'array' => 'The :attribute field must have between :min and :max items.',
'file' => 'The :attribute field must be between :min and :max kilobytes.',
'numeric' => 'The :attribute field must be between :min and :max.',
'string' => 'The :attribute field must be between :min and :max characters.',
],
'boolean' => 'The :attribute field must be true or false.',
'can' => 'The :attribute field contains an unauthorized value.',
'confirmed' => 'The :attribute field confirmation does not match.',
'contains' => 'The :attribute field is missing a required value.',
'current_password' => 'The password is incorrect.',
'date' => 'The :attribute field must be a valid date.',
'date_equals' => 'The :attribute field must be a date equal to :date.',
'date_format' => 'The :attribute field must match the format :format.',
'decimal' => 'The :attribute field must have :decimal decimal places.',
'declined' => 'The :attribute field must be declined.',
'declined_if' => 'The :attribute field must be declined when :other is :value.',
'different' => 'The :attribute field and :other must be different.',
'digits' => 'The :attribute field must be :digits digits.',
'digits_between' => 'The :attribute field must be between :min and :max digits.',
'dimensions' => 'The :attribute field has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'doesnt_end_with' => 'The :attribute field must not end with one of the following: :values.',
'doesnt_start_with' => 'The :attribute field must not start with one of the following: :values.',
'email' => 'The :attribute field must be a valid email address.',
'ends_with' => 'The :attribute field must end with one of the following: :values.',
'enum' => 'The selected :attribute is invalid.',
'exists' => 'The selected :attribute is invalid.',
'extensions' => 'The :attribute field must have one of the following extensions: :values.',
'file' => 'The :attribute field must be a file.',
'filled' => 'The :attribute field must have a value.',
'gt' => [
'array' => 'The :attribute field must have more than :value items.',
'file' => 'The :attribute field must be greater than :value kilobytes.',
'numeric' => 'The :attribute field must be greater than :value.',
'string' => 'The :attribute field must be greater than :value characters.',
],
'gte' => [
'array' => 'The :attribute field must have :value items or more.',
'file' => 'The :attribute field must be greater than or equal to :value kilobytes.',
'numeric' => 'The :attribute field must be greater than or equal to :value.',
'string' => 'The :attribute field must be greater than or equal to :value characters.',
],
'hex_color' => 'The :attribute field must be a valid hexadecimal color.',
'image' => 'The :attribute field must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field must exist in :other.',
'integer' => 'The :attribute field must be an integer.',
'ip' => 'The :attribute field must be a valid IP address.',
'ipv4' => 'The :attribute field must be a valid IPv4 address.',
'ipv6' => 'The :attribute field must be a valid IPv6 address.',
'json' => 'The :attribute field must be a valid JSON string.',
'list' => 'The :attribute field must be a list.',
'lowercase' => 'The :attribute field must be lowercase.',
'lt' => [
'array' => 'The :attribute field must have less than :value items.',
'file' => 'The :attribute field must be less than :value kilobytes.',
'numeric' => 'The :attribute field must be less than :value.',
'string' => 'The :attribute field must be less than :value characters.',
],
'lte' => [
'array' => 'The :attribute field must not have more than :value items.',
'file' => 'The :attribute field must be less than or equal to :value kilobytes.',
'numeric' => 'The :attribute field must be less than or equal to :value.',
'string' => 'The :attribute field must be less than or equal to :value characters.',
],
'mac_address' => 'The :attribute field must be a valid MAC address.',
'max' => [
'array' => 'The :attribute field must not have more than :max items.',
'file' => 'The :attribute field must not be greater than :max kilobytes.',
'numeric' => 'The :attribute field must not be greater than :max.',
'string' => 'The :attribute field must not be greater than :max characters.',
],
'max_digits' => 'The :attribute field must not have more than :max digits.',
'mimes' => 'The :attribute field must be a file of type: :values.',
'mimetypes' => 'The :attribute field must be a file of type: :values.',
'min' => [
'array' => 'The :attribute field must have at least :min items.',
'file' => 'The :attribute field must be at least :min kilobytes.',
'numeric' => 'The :attribute field must be at least :min.',
'string' => 'The :attribute field must be at least :min characters.',
],
'min_digits' => 'The :attribute field must have at least :min digits.',
'missing' => 'The :attribute field must be missing.',
'missing_if' => 'The :attribute field must be missing when :other is :value.',
'missing_unless' => 'The :attribute field must be missing unless :other is :value.',
'missing_with' => 'The :attribute field must be missing when :values is present.',
'missing_with_all' => 'The :attribute field must be missing when :values are present.',
'multiple_of' => 'The :attribute field must be a multiple of :value.',
'not_in' => 'The selected :attribute is invalid.',
'not_regex' => 'The :attribute field format is invalid.',
'numeric' => 'The :attribute field must be a number.',
'password' => [
'letters' => 'The :attribute field must contain at least one letter.',
'mixed' => 'The :attribute field must contain at least one uppercase and one lowercase letter.',
'numbers' => 'The :attribute field must contain at least one number.',
'symbols' => 'The :attribute field must contain at least one symbol.',
'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.',
],
'present' => 'The :attribute field must be present.',
'present_if' => 'The :attribute field must be present when :other is :value.',
'present_unless' => 'The :attribute field must be present unless :other is :value.',
'present_with' => 'The :attribute field must be present when :values is present.',
'present_with_all' => 'The :attribute field must be present when :values are present.',
'prohibited' => 'The :attribute field is prohibited.',
'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
'prohibits' => 'The :attribute field prohibits :other from being present.',
'regex' => 'The :attribute field format is invalid.',
'required' => 'The :attribute field is required.',
'required_array_keys' => 'The :attribute field must contain entries for: :values.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_if_accepted' => 'The :attribute field is required when :other is accepted.',
'required_if_declined' => 'The :attribute field is required when :other is declined.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values are present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute field must match :other.',
'size' => [
'array' => 'The :attribute field must contain :size items.',
'file' => 'The :attribute field must be :size kilobytes.',
'numeric' => 'The :attribute field must be :size.',
'string' => 'The :attribute field must be :size characters.',
],
'starts_with' => 'The :attribute field must start with one of the following: :values.',
'string' => 'The :attribute field must be a string.',
'timezone' => 'The :attribute field must be a valid timezone.',
'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.',
'uppercase' => 'The :attribute field must be uppercase.',
'url' => 'The :attribute field must be a valid URL.',
'ulid' => 'The :attribute field must be a valid ULID.',
'uuid' => 'The :attribute field must be a valid UUID.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap our attribute placeholder
| with something more reader friendly such as "E-Mail Address" instead
| of "email". This simply helps us make our message more expressive.
|
*/
'attributes' => [],
];

14
lang/zh_CN/menu.php Normal file
View File

@ -0,0 +1,14 @@
<?php
return [
'statistics' => '统计',
'stats' => '统计',
'monitor' => '监控中心',
'security' => '安全策略',
'control' => '控制',
'setting' => '设置',
'demo' => '演示',
'nasa' => 'nasa',
'helper' => '帮助',
'node' => '节点',
];

1
node_modules/.bin/autoprefixer generated vendored Symbolic link
View File

@ -0,0 +1 @@
../autoprefixer/bin/autoprefixer

1
node_modules/.bin/baseline-browser-mapping generated vendored Symbolic link
View File

@ -0,0 +1 @@
../baseline-browser-mapping/dist/cli.cjs

1
node_modules/.bin/browserslist generated vendored Symbolic link
View File

@ -0,0 +1 @@
../browserslist/cli.js

1
node_modules/.bin/clean-orphaned-assets generated vendored Symbolic link
View File

@ -0,0 +1 @@
../laravel-vite-plugin/bin/clean.js

1
node_modules/.bin/conc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../concurrently/dist/bin/concurrently.js

1
node_modules/.bin/concurrently generated vendored Symbolic link
View File

@ -0,0 +1 @@
../concurrently/dist/bin/concurrently.js

1
node_modules/.bin/cssesc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../cssesc/bin/cssesc

1
node_modules/.bin/esbuild generated vendored Symbolic link
View File

@ -0,0 +1 @@
../esbuild/bin/esbuild

1
node_modules/.bin/jiti generated vendored Symbolic link
View File

@ -0,0 +1 @@
../jiti/bin/jiti.js

1
node_modules/.bin/marked generated vendored Symbolic link
View File

@ -0,0 +1 @@
../marked/bin/marked.js

1
node_modules/.bin/nanoid generated vendored Symbolic link
View File

@ -0,0 +1 @@
../nanoid/bin/nanoid.cjs

1
node_modules/.bin/resolve generated vendored Symbolic link
View File

@ -0,0 +1 @@
../resolve/bin/resolve

1
node_modules/.bin/rollup generated vendored Symbolic link
View File

@ -0,0 +1 @@
../rollup/dist/bin/rollup

1
node_modules/.bin/sucrase generated vendored Symbolic link
View File

@ -0,0 +1 @@
../sucrase/bin/sucrase

1
node_modules/.bin/sucrase-node generated vendored Symbolic link
View File

@ -0,0 +1 @@
../sucrase/bin/sucrase-node

1
node_modules/.bin/tailwind generated vendored Symbolic link
View File

@ -0,0 +1 @@
../tailwindcss/lib/cli.js

1
node_modules/.bin/tailwindcss generated vendored Symbolic link
View File

@ -0,0 +1 @@
../tailwindcss/lib/cli.js

1
node_modules/.bin/tree-kill generated vendored Symbolic link
View File

@ -0,0 +1 @@
../tree-kill/cli.js

1
node_modules/.bin/update-browserslist-db generated vendored Symbolic link
View File

@ -0,0 +1 @@
../update-browserslist-db/cli.js

1
node_modules/.bin/vite generated vendored Symbolic link
View File

@ -0,0 +1 @@
../vite/bin/vite.js

2701
node_modules/.package-lock.json generated vendored Normal file

File diff suppressed because it is too large Load Diff

254
node_modules/.vite/deps/@tiptap_core.js generated vendored Normal file
View File

@ -0,0 +1,254 @@
import {
CommandManager,
Editor,
Extendable,
Extension,
Fragment6,
InputRule,
MappablePosition,
Mark,
MarkView,
Node3,
NodePos,
NodeView,
PasteRule,
ResizableNodeView,
ResizableNodeview,
Tracker,
attrsEqual,
callOrReturn,
canInsertNode,
combineTransactionSteps,
commands_exports,
createAtomBlockMarkdownSpec,
createBlockMarkdownSpec,
createChainableState,
createDocument,
createInlineMarkdownSpec,
createMappablePosition,
createNodeFromContent,
createStyleTag,
decodeHtmlEntities,
defaultBlockAt,
deleteProps,
elementFromString,
encodeHtmlEntities,
escapeForRegEx,
extensions_exports,
findChildren,
findChildrenInRange,
findDuplicates,
findParentNode,
findParentNodeClosestToPos,
flattenExtensions,
fromString,
generateHTML,
generateJSON,
generateText,
getAttributes,
getAttributesFromExtensions,
getChangedRanges,
getDebugJSON,
getExtensionField,
getHTMLFromFragment,
getMarkAttributes,
getMarkRange,
getMarkType,
getMarksBetween,
getNodeAtPosition,
getNodeAttributes,
getNodeType,
getRenderedAttributes,
getSchema,
getSchemaByResolvedExtensions,
getSchemaTypeByName,
getSchemaTypeNameByName,
getSplittedAttributes,
getStyleProperty,
getText,
getTextBetween,
getTextContentFromNodes,
getTextSerializersFromSchema,
getUpdatedPosition,
h,
injectExtensionAttributesToParseRule,
inputRulesPlugin,
isActive,
isAndroid,
isAtEndOfNode,
isAtStartOfNode,
isEmptyObject,
isExtensionRulesEnabled,
isFirefox,
isFunction,
isList,
isMacOS,
isMarkActive,
isNodeActive,
isNodeEmpty,
isNodeSelection,
isNodeViewSelected,
isNumber,
isPlainObject,
isRegExp,
isSafari,
isString,
isTextSelection,
isiOS,
markInputRule,
markPasteRule,
markdown_exports,
marksEqual,
mergeAttributes,
mergeDeep,
minMax,
nodeInputRule,
nodePasteRule,
objectIncludes,
parseAttributes,
parseIndentedBlocks,
pasteRulesPlugin,
posToDOMRect,
removeDuplicates,
renderNestedMarkdownContent,
resolveExtensions,
resolveFocusPosition,
rewriteUnknownContent,
selectionToInsertionEnd,
serializeAttributes,
sortExtensions,
splitExtensions,
textInputRule,
textPasteRule,
textblockTypeInputRule,
updateMarkViewAttributes,
wrappingInputRule
} from "./chunk-Y2TX42W2.js";
import "./chunk-UVKRO5ER.js";
export {
CommandManager,
Editor,
Extendable,
Extension,
Fragment6 as Fragment,
InputRule,
MappablePosition,
Mark,
MarkView,
Node3 as Node,
NodePos,
NodeView,
PasteRule,
ResizableNodeView,
ResizableNodeview,
Tracker,
attrsEqual,
callOrReturn,
canInsertNode,
combineTransactionSteps,
commands_exports as commands,
createAtomBlockMarkdownSpec,
createBlockMarkdownSpec,
createChainableState,
createDocument,
h as createElement,
createInlineMarkdownSpec,
createMappablePosition,
createNodeFromContent,
createStyleTag,
decodeHtmlEntities,
defaultBlockAt,
deleteProps,
elementFromString,
encodeHtmlEntities,
escapeForRegEx,
extensions_exports as extensions,
findChildren,
findChildrenInRange,
findDuplicates,
findParentNode,
findParentNodeClosestToPos,
flattenExtensions,
fromString,
generateHTML,
generateJSON,
generateText,
getAttributes,
getAttributesFromExtensions,
getChangedRanges,
getDebugJSON,
getExtensionField,
getHTMLFromFragment,
getMarkAttributes,
getMarkRange,
getMarkType,
getMarksBetween,
getNodeAtPosition,
getNodeAttributes,
getNodeType,
getRenderedAttributes,
getSchema,
getSchemaByResolvedExtensions,
getSchemaTypeByName,
getSchemaTypeNameByName,
getSplittedAttributes,
getStyleProperty,
getText,
getTextBetween,
getTextContentFromNodes,
getTextSerializersFromSchema,
getUpdatedPosition,
h,
injectExtensionAttributesToParseRule,
inputRulesPlugin,
isActive,
isAndroid,
isAtEndOfNode,
isAtStartOfNode,
isEmptyObject,
isExtensionRulesEnabled,
isFirefox,
isFunction,
isList,
isMacOS,
isMarkActive,
isNodeActive,
isNodeEmpty,
isNodeSelection,
isNodeViewSelected,
isNumber,
isPlainObject,
isRegExp,
isSafari,
isString,
isTextSelection,
isiOS,
markInputRule,
markPasteRule,
markdown_exports as markdown,
marksEqual,
mergeAttributes,
mergeDeep,
minMax,
nodeInputRule,
nodePasteRule,
objectIncludes,
parseAttributes,
parseIndentedBlocks,
pasteRulesPlugin,
posToDOMRect,
removeDuplicates,
renderNestedMarkdownContent,
resolveExtensions,
resolveFocusPosition,
rewriteUnknownContent,
selectionToInsertionEnd,
serializeAttributes,
sortExtensions,
splitExtensions,
textInputRule,
textPasteRule,
textblockTypeInputRule,
updateMarkViewAttributes,
wrappingInputRule
};

7
node_modules/.vite/deps/@tiptap_core.js.map generated vendored Normal file
View File

@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}

2598
node_modules/.vite/deps/@tiptap_markdown.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

7
node_modules/.vite/deps/@tiptap_markdown.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

5530
node_modules/.vite/deps/@tiptap_starter-kit.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

7
node_modules/.vite/deps/@tiptap_starter-kit.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

46
node_modules/.vite/deps/_metadata.json generated vendored Normal file
View File

@ -0,0 +1,46 @@
{
"hash": "b574fc88",
"configHash": "b07a9909",
"lockfileHash": "c8861203",
"browserHash": "04981c78",
"optimized": {
"axios": {
"src": "../../axios/index.js",
"file": "axios.js",
"fileHash": "20312a3d",
"needsInterop": false
},
"jquery": {
"src": "../../jquery/dist-module/jquery.module.js",
"file": "jquery.js",
"fileHash": "6c09c645",
"needsInterop": false
},
"@tiptap/core": {
"src": "../../@tiptap/core/dist/index.js",
"file": "@tiptap_core.js",
"fileHash": "4c6bef51",
"needsInterop": false
},
"@tiptap/starter-kit": {
"src": "../../@tiptap/starter-kit/dist/index.js",
"file": "@tiptap_starter-kit.js",
"fileHash": "82b0765b",
"needsInterop": false
},
"@tiptap/markdown": {
"src": "../../@tiptap/markdown/dist/index.js",
"file": "@tiptap_markdown.js",
"fileHash": "38efcae8",
"needsInterop": false
}
},
"chunks": {
"chunk-Y2TX42W2": {
"file": "chunk-Y2TX42W2.js"
},
"chunk-UVKRO5ER": {
"file": "chunk-UVKRO5ER.js"
}
}
}

3182
node_modules/.vite/deps/axios.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

7
node_modules/.vite/deps/axios.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

12
node_modules/.vite/deps/chunk-UVKRO5ER.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
export {
__export,
__publicField
};

7
node_modules/.vite/deps/chunk-UVKRO5ER.js.map generated vendored Normal file
View File

@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}

19065
node_modules/.vite/deps/chunk-Y2TX42W2.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

7
node_modules/.vite/deps/chunk-Y2TX42W2.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

5872
node_modules/.vite/deps/jquery.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

7
node_modules/.vite/deps/jquery.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

3
node_modules/.vite/deps/package.json generated vendored Normal file
View File

@ -0,0 +1,3 @@
{
"type": "module"
}

128
node_modules/@alloc/quick-lru/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,128 @@
declare namespace QuickLRU {
interface Options<KeyType, ValueType> {
/**
The maximum number of milliseconds an item should remain in the cache.
@default Infinity
By default, `maxAge` will be `Infinity`, which means that items will never expire.
Lazy expiration upon the next write or read call.
Individual expiration of an item can be specified by the `set(key, value, maxAge)` method.
*/
readonly maxAge?: number;
/**
The maximum number of items before evicting the least recently used items.
*/
readonly maxSize: number;
/**
Called right before an item is evicted from the cache.
Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`).
*/
onEviction?: (key: KeyType, value: ValueType) => void;
}
}
declare class QuickLRU<KeyType, ValueType>
implements Iterable<[KeyType, ValueType]> {
/**
The stored item count.
*/
readonly size: number;
/**
Simple ["Least Recently Used" (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29).
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
@example
```
import QuickLRU = require('quick-lru');
const lru = new QuickLRU({maxSize: 1000});
lru.set('🦄', '🌈');
lru.has('🦄');
//=> true
lru.get('🦄');
//=> '🌈'
```
*/
constructor(options: QuickLRU.Options<KeyType, ValueType>);
[Symbol.iterator](): IterableIterator<[KeyType, ValueType]>;
/**
Set an item. Returns the instance.
Individual expiration of an item can be specified with the `maxAge` option. If not specified, the global `maxAge` value will be used in case it is specified in the constructor, otherwise the item will never expire.
@returns The list instance.
*/
set(key: KeyType, value: ValueType, options?: {maxAge?: number}): this;
/**
Get an item.
@returns The stored item or `undefined`.
*/
get(key: KeyType): ValueType | undefined;
/**
Check if an item exists.
*/
has(key: KeyType): boolean;
/**
Get an item without marking it as recently used.
@returns The stored item or `undefined`.
*/
peek(key: KeyType): ValueType | undefined;
/**
Delete an item.
@returns `true` if the item is removed or `false` if the item doesn't exist.
*/
delete(key: KeyType): boolean;
/**
Delete all items.
*/
clear(): void;
/**
Update the `maxSize` in-place, discarding items as necessary. Insertion order is mostly preserved, though this is not a strong guarantee.
Useful for on-the-fly tuning of cache sizes in live systems.
*/
resize(maxSize: number): void;
/**
Iterable for all the keys.
*/
keys(): IterableIterator<KeyType>;
/**
Iterable for all the values.
*/
values(): IterableIterator<ValueType>;
/**
Iterable for all entries, starting with the oldest (ascending in recency).
*/
entriesAscending(): IterableIterator<[KeyType, ValueType]>;
/**
Iterable for all entries, starting with the newest (descending in recency).
*/
entriesDescending(): IterableIterator<[KeyType, ValueType]>;
}
export = QuickLRU;

263
node_modules/@alloc/quick-lru/index.js generated vendored Normal file
View File

@ -0,0 +1,263 @@
'use strict';
class QuickLRU {
constructor(options = {}) {
if (!(options.maxSize && options.maxSize > 0)) {
throw new TypeError('`maxSize` must be a number greater than 0');
}
if (typeof options.maxAge === 'number' && options.maxAge === 0) {
throw new TypeError('`maxAge` must be a number greater than 0');
}
this.maxSize = options.maxSize;
this.maxAge = options.maxAge || Infinity;
this.onEviction = options.onEviction;
this.cache = new Map();
this.oldCache = new Map();
this._size = 0;
}
_emitEvictions(cache) {
if (typeof this.onEviction !== 'function') {
return;
}
for (const [key, item] of cache) {
this.onEviction(key, item.value);
}
}
_deleteIfExpired(key, item) {
if (typeof item.expiry === 'number' && item.expiry <= Date.now()) {
if (typeof this.onEviction === 'function') {
this.onEviction(key, item.value);
}
return this.delete(key);
}
return false;
}
_getOrDeleteIfExpired(key, item) {
const deleted = this._deleteIfExpired(key, item);
if (deleted === false) {
return item.value;
}
}
_getItemValue(key, item) {
return item.expiry ? this._getOrDeleteIfExpired(key, item) : item.value;
}
_peek(key, cache) {
const item = cache.get(key);
return this._getItemValue(key, item);
}
_set(key, value) {
this.cache.set(key, value);
this._size++;
if (this._size >= this.maxSize) {
this._size = 0;
this._emitEvictions(this.oldCache);
this.oldCache = this.cache;
this.cache = new Map();
}
}
_moveToRecent(key, item) {
this.oldCache.delete(key);
this._set(key, item);
}
* _entriesAscending() {
for (const item of this.oldCache) {
const [key, value] = item;
if (!this.cache.has(key)) {
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield item;
}
}
}
for (const item of this.cache) {
const [key, value] = item;
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield item;
}
}
}
get(key) {
if (this.cache.has(key)) {
const item = this.cache.get(key);
return this._getItemValue(key, item);
}
if (this.oldCache.has(key)) {
const item = this.oldCache.get(key);
if (this._deleteIfExpired(key, item) === false) {
this._moveToRecent(key, item);
return item.value;
}
}
}
set(key, value, {maxAge = this.maxAge === Infinity ? undefined : Date.now() + this.maxAge} = {}) {
if (this.cache.has(key)) {
this.cache.set(key, {
value,
maxAge
});
} else {
this._set(key, {value, expiry: maxAge});
}
}
has(key) {
if (this.cache.has(key)) {
return !this._deleteIfExpired(key, this.cache.get(key));
}
if (this.oldCache.has(key)) {
return !this._deleteIfExpired(key, this.oldCache.get(key));
}
return false;
}
peek(key) {
if (this.cache.has(key)) {
return this._peek(key, this.cache);
}
if (this.oldCache.has(key)) {
return this._peek(key, this.oldCache);
}
}
delete(key) {
const deleted = this.cache.delete(key);
if (deleted) {
this._size--;
}
return this.oldCache.delete(key) || deleted;
}
clear() {
this.cache.clear();
this.oldCache.clear();
this._size = 0;
}
resize(newSize) {
if (!(newSize && newSize > 0)) {
throw new TypeError('`maxSize` must be a number greater than 0');
}
const items = [...this._entriesAscending()];
const removeCount = items.length - newSize;
if (removeCount < 0) {
this.cache = new Map(items);
this.oldCache = new Map();
this._size = items.length;
} else {
if (removeCount > 0) {
this._emitEvictions(items.slice(0, removeCount));
}
this.oldCache = new Map(items.slice(removeCount));
this.cache = new Map();
this._size = 0;
}
this.maxSize = newSize;
}
* keys() {
for (const [key] of this) {
yield key;
}
}
* values() {
for (const [, value] of this) {
yield value;
}
}
* [Symbol.iterator]() {
for (const item of this.cache) {
const [key, value] = item;
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield [key, value.value];
}
}
for (const item of this.oldCache) {
const [key, value] = item;
if (!this.cache.has(key)) {
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield [key, value.value];
}
}
}
}
* entriesDescending() {
let items = [...this.cache];
for (let i = items.length - 1; i >= 0; --i) {
const item = items[i];
const [key, value] = item;
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield [key, value.value];
}
}
items = [...this.oldCache];
for (let i = items.length - 1; i >= 0; --i) {
const item = items[i];
const [key, value] = item;
if (!this.cache.has(key)) {
const deleted = this._deleteIfExpired(key, value);
if (deleted === false) {
yield [key, value.value];
}
}
}
}
* entriesAscending() {
for (const [key, value] of this._entriesAscending()) {
yield [key, value.value];
}
}
get size() {
if (!this._size) {
return this.oldCache.size;
}
let oldCacheSize = 0;
for (const key of this.oldCache.keys()) {
if (!this.cache.has(key)) {
oldCacheSize++;
}
}
return Math.min(this._size + oldCacheSize, this.maxSize);
}
}
module.exports = QuickLRU;

9
node_modules/@alloc/quick-lru/license generated vendored Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.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.

43
node_modules/@alloc/quick-lru/package.json generated vendored Normal file
View File

@ -0,0 +1,43 @@
{
"name": "@alloc/quick-lru",
"version": "5.2.0",
"description": "Simple “Least Recently Used” (LRU) cache",
"license": "MIT",
"repository": "sindresorhus/quick-lru",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=10"
},
"scripts": {
"test": "xo && nyc ava && tsd"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"lru",
"quick",
"cache",
"caching",
"least",
"recently",
"used",
"fast",
"map",
"hash",
"buffer"
],
"devDependencies": {
"ava": "^2.0.0",
"coveralls": "^3.0.3",
"nyc": "^15.0.0",
"tsd": "^0.11.0",
"xo": "^0.26.0"
}
}

BIN
node_modules/@esbuild/darwin-x64/bin/esbuild generated vendored Executable file

Binary file not shown.

20
node_modules/@esbuild/darwin-x64/package.json generated vendored Normal file
View File

@ -0,0 +1,20 @@
{
"name": "@esbuild/darwin-x64",
"version": "0.25.12",
"description": "The macOS 64-bit binary for esbuild, a JavaScript bundler.",
"repository": {
"type": "git",
"url": "git+https://github.com/evanw/esbuild.git"
},
"license": "MIT",
"preferUnplugged": true,
"engines": {
"node": ">=18"
},
"os": [
"darwin"
],
"cpu": [
"x64"
]
}

19
node_modules/@jridgewell/gen-mapping/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright 2024 Justin Ridgewell <justin@ridgewell.name>
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.

View File

@ -0,0 +1,292 @@
// src/set-array.ts
var SetArray = class {
constructor() {
this._indexes = { __proto__: null };
this.array = [];
}
};
function cast(set) {
return set;
}
function get(setarr, key) {
return cast(setarr)._indexes[key];
}
function put(setarr, key) {
const index = get(setarr, key);
if (index !== void 0) return index;
const { array, _indexes: indexes } = cast(setarr);
const length = array.push(key);
return indexes[key] = length - 1;
}
function remove(setarr, key) {
const index = get(setarr, key);
if (index === void 0) return;
const { array, _indexes: indexes } = cast(setarr);
for (let i = index + 1; i < array.length; i++) {
const k = array[i];
array[i - 1] = k;
indexes[k]--;
}
indexes[key] = void 0;
array.pop();
}
// src/gen-mapping.ts
import {
encode
} from "@jridgewell/sourcemap-codec";
import { TraceMap, decodedMappings } from "@jridgewell/trace-mapping";
// src/sourcemap-segment.ts
var COLUMN = 0;
var SOURCES_INDEX = 1;
var SOURCE_LINE = 2;
var SOURCE_COLUMN = 3;
var NAMES_INDEX = 4;
// src/gen-mapping.ts
var NO_NAME = -1;
var GenMapping = class {
constructor({ file, sourceRoot } = {}) {
this._names = new SetArray();
this._sources = new SetArray();
this._sourcesContent = [];
this._mappings = [];
this.file = file;
this.sourceRoot = sourceRoot;
this._ignoreList = new SetArray();
}
};
function cast2(map) {
return map;
}
function addSegment(map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) {
return addSegmentInternal(
false,
map,
genLine,
genColumn,
source,
sourceLine,
sourceColumn,
name,
content
);
}
function addMapping(map, mapping) {
return addMappingInternal(false, map, mapping);
}
var maybeAddSegment = (map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) => {
return addSegmentInternal(
true,
map,
genLine,
genColumn,
source,
sourceLine,
sourceColumn,
name,
content
);
};
var maybeAddMapping = (map, mapping) => {
return addMappingInternal(true, map, mapping);
};
function setSourceContent(map, source, content) {
const {
_sources: sources,
_sourcesContent: sourcesContent
// _originalScopes: originalScopes,
} = cast2(map);
const index = put(sources, source);
sourcesContent[index] = content;
}
function setIgnore(map, source, ignore = true) {
const {
_sources: sources,
_sourcesContent: sourcesContent,
_ignoreList: ignoreList
// _originalScopes: originalScopes,
} = cast2(map);
const index = put(sources, source);
if (index === sourcesContent.length) sourcesContent[index] = null;
if (ignore) put(ignoreList, index);
else remove(ignoreList, index);
}
function toDecodedMap(map) {
const {
_mappings: mappings,
_sources: sources,
_sourcesContent: sourcesContent,
_names: names,
_ignoreList: ignoreList
// _originalScopes: originalScopes,
// _generatedRanges: generatedRanges,
} = cast2(map);
removeEmptyFinalLines(mappings);
return {
version: 3,
file: map.file || void 0,
names: names.array,
sourceRoot: map.sourceRoot || void 0,
sources: sources.array,
sourcesContent,
mappings,
// originalScopes,
// generatedRanges,
ignoreList: ignoreList.array
};
}
function toEncodedMap(map) {
const decoded = toDecodedMap(map);
return Object.assign({}, decoded, {
// originalScopes: decoded.originalScopes.map((os) => encodeOriginalScopes(os)),
// generatedRanges: encodeGeneratedRanges(decoded.generatedRanges as GeneratedRange[]),
mappings: encode(decoded.mappings)
});
}
function fromMap(input) {
const map = new TraceMap(input);
const gen = new GenMapping({ file: map.file, sourceRoot: map.sourceRoot });
putAll(cast2(gen)._names, map.names);
putAll(cast2(gen)._sources, map.sources);
cast2(gen)._sourcesContent = map.sourcesContent || map.sources.map(() => null);
cast2(gen)._mappings = decodedMappings(map);
if (map.ignoreList) putAll(cast2(gen)._ignoreList, map.ignoreList);
return gen;
}
function allMappings(map) {
const out = [];
const { _mappings: mappings, _sources: sources, _names: names } = cast2(map);
for (let i = 0; i < mappings.length; i++) {
const line = mappings[i];
for (let j = 0; j < line.length; j++) {
const seg = line[j];
const generated = { line: i + 1, column: seg[COLUMN] };
let source = void 0;
let original = void 0;
let name = void 0;
if (seg.length !== 1) {
source = sources.array[seg[SOURCES_INDEX]];
original = { line: seg[SOURCE_LINE] + 1, column: seg[SOURCE_COLUMN] };
if (seg.length === 5) name = names.array[seg[NAMES_INDEX]];
}
out.push({ generated, source, original, name });
}
}
return out;
}
function addSegmentInternal(skipable, map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) {
const {
_mappings: mappings,
_sources: sources,
_sourcesContent: sourcesContent,
_names: names
// _originalScopes: originalScopes,
} = cast2(map);
const line = getIndex(mappings, genLine);
const index = getColumnIndex(line, genColumn);
if (!source) {
if (skipable && skipSourceless(line, index)) return;
return insert(line, index, [genColumn]);
}
assert(sourceLine);
assert(sourceColumn);
const sourcesIndex = put(sources, source);
const namesIndex = name ? put(names, name) : NO_NAME;
if (sourcesIndex === sourcesContent.length) sourcesContent[sourcesIndex] = content != null ? content : null;
if (skipable && skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex)) {
return;
}
return insert(
line,
index,
name ? [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex] : [genColumn, sourcesIndex, sourceLine, sourceColumn]
);
}
function assert(_val) {
}
function getIndex(arr, index) {
for (let i = arr.length; i <= index; i++) {
arr[i] = [];
}
return arr[index];
}
function getColumnIndex(line, genColumn) {
let index = line.length;
for (let i = index - 1; i >= 0; index = i--) {
const current = line[i];
if (genColumn >= current[COLUMN]) break;
}
return index;
}
function insert(array, index, value) {
for (let i = array.length; i > index; i--) {
array[i] = array[i - 1];
}
array[index] = value;
}
function removeEmptyFinalLines(mappings) {
const { length } = mappings;
let len = length;
for (let i = len - 1; i >= 0; len = i, i--) {
if (mappings[i].length > 0) break;
}
if (len < length) mappings.length = len;
}
function putAll(setarr, array) {
for (let i = 0; i < array.length; i++) put(setarr, array[i]);
}
function skipSourceless(line, index) {
if (index === 0) return true;
const prev = line[index - 1];
return prev.length === 1;
}
function skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex) {
if (index === 0) return false;
const prev = line[index - 1];
if (prev.length === 1) return false;
return sourcesIndex === prev[SOURCES_INDEX] && sourceLine === prev[SOURCE_LINE] && sourceColumn === prev[SOURCE_COLUMN] && namesIndex === (prev.length === 5 ? prev[NAMES_INDEX] : NO_NAME);
}
function addMappingInternal(skipable, map, mapping) {
const { generated, source, original, name, content } = mapping;
if (!source) {
return addSegmentInternal(
skipable,
map,
generated.line - 1,
generated.column,
null,
null,
null,
null,
null
);
}
assert(original);
return addSegmentInternal(
skipable,
map,
generated.line - 1,
generated.column,
source,
original.line - 1,
original.column,
name,
content
);
}
export {
GenMapping,
addMapping,
addSegment,
allMappings,
fromMap,
maybeAddMapping,
maybeAddSegment,
setIgnore,
setSourceContent,
toDecodedMap,
toEncodedMap
};
//# sourceMappingURL=gen-mapping.mjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,358 @@
(function (global, factory) {
if (typeof exports === 'object' && typeof module !== 'undefined') {
factory(module, require('@jridgewell/sourcemap-codec'), require('@jridgewell/trace-mapping'));
module.exports = def(module);
} else if (typeof define === 'function' && define.amd) {
define(['module', '@jridgewell/sourcemap-codec', '@jridgewell/trace-mapping'], function(mod) {
factory.apply(this, arguments);
mod.exports = def(mod);
});
} else {
const mod = { exports: {} };
factory(mod, global.sourcemapCodec, global.traceMapping);
global = typeof globalThis !== 'undefined' ? globalThis : global || self;
global.genMapping = def(mod);
}
function def(m) { return 'default' in m.exports ? m.exports.default : m.exports; }
})(this, (function (module, require_sourcemapCodec, require_traceMapping) {
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// umd:@jridgewell/sourcemap-codec
var require_sourcemap_codec = __commonJS({
"umd:@jridgewell/sourcemap-codec"(exports, module2) {
module2.exports = require_sourcemapCodec;
}
});
// umd:@jridgewell/trace-mapping
var require_trace_mapping = __commonJS({
"umd:@jridgewell/trace-mapping"(exports, module2) {
module2.exports = require_traceMapping;
}
});
// src/gen-mapping.ts
var gen_mapping_exports = {};
__export(gen_mapping_exports, {
GenMapping: () => GenMapping,
addMapping: () => addMapping,
addSegment: () => addSegment,
allMappings: () => allMappings,
fromMap: () => fromMap,
maybeAddMapping: () => maybeAddMapping,
maybeAddSegment: () => maybeAddSegment,
setIgnore: () => setIgnore,
setSourceContent: () => setSourceContent,
toDecodedMap: () => toDecodedMap,
toEncodedMap: () => toEncodedMap
});
module.exports = __toCommonJS(gen_mapping_exports);
// src/set-array.ts
var SetArray = class {
constructor() {
this._indexes = { __proto__: null };
this.array = [];
}
};
function cast(set) {
return set;
}
function get(setarr, key) {
return cast(setarr)._indexes[key];
}
function put(setarr, key) {
const index = get(setarr, key);
if (index !== void 0) return index;
const { array, _indexes: indexes } = cast(setarr);
const length = array.push(key);
return indexes[key] = length - 1;
}
function remove(setarr, key) {
const index = get(setarr, key);
if (index === void 0) return;
const { array, _indexes: indexes } = cast(setarr);
for (let i = index + 1; i < array.length; i++) {
const k = array[i];
array[i - 1] = k;
indexes[k]--;
}
indexes[key] = void 0;
array.pop();
}
// src/gen-mapping.ts
var import_sourcemap_codec = __toESM(require_sourcemap_codec());
var import_trace_mapping = __toESM(require_trace_mapping());
// src/sourcemap-segment.ts
var COLUMN = 0;
var SOURCES_INDEX = 1;
var SOURCE_LINE = 2;
var SOURCE_COLUMN = 3;
var NAMES_INDEX = 4;
// src/gen-mapping.ts
var NO_NAME = -1;
var GenMapping = class {
constructor({ file, sourceRoot } = {}) {
this._names = new SetArray();
this._sources = new SetArray();
this._sourcesContent = [];
this._mappings = [];
this.file = file;
this.sourceRoot = sourceRoot;
this._ignoreList = new SetArray();
}
};
function cast2(map) {
return map;
}
function addSegment(map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) {
return addSegmentInternal(
false,
map,
genLine,
genColumn,
source,
sourceLine,
sourceColumn,
name,
content
);
}
function addMapping(map, mapping) {
return addMappingInternal(false, map, mapping);
}
var maybeAddSegment = (map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) => {
return addSegmentInternal(
true,
map,
genLine,
genColumn,
source,
sourceLine,
sourceColumn,
name,
content
);
};
var maybeAddMapping = (map, mapping) => {
return addMappingInternal(true, map, mapping);
};
function setSourceContent(map, source, content) {
const {
_sources: sources,
_sourcesContent: sourcesContent
// _originalScopes: originalScopes,
} = cast2(map);
const index = put(sources, source);
sourcesContent[index] = content;
}
function setIgnore(map, source, ignore = true) {
const {
_sources: sources,
_sourcesContent: sourcesContent,
_ignoreList: ignoreList
// _originalScopes: originalScopes,
} = cast2(map);
const index = put(sources, source);
if (index === sourcesContent.length) sourcesContent[index] = null;
if (ignore) put(ignoreList, index);
else remove(ignoreList, index);
}
function toDecodedMap(map) {
const {
_mappings: mappings,
_sources: sources,
_sourcesContent: sourcesContent,
_names: names,
_ignoreList: ignoreList
// _originalScopes: originalScopes,
// _generatedRanges: generatedRanges,
} = cast2(map);
removeEmptyFinalLines(mappings);
return {
version: 3,
file: map.file || void 0,
names: names.array,
sourceRoot: map.sourceRoot || void 0,
sources: sources.array,
sourcesContent,
mappings,
// originalScopes,
// generatedRanges,
ignoreList: ignoreList.array
};
}
function toEncodedMap(map) {
const decoded = toDecodedMap(map);
return Object.assign({}, decoded, {
// originalScopes: decoded.originalScopes.map((os) => encodeOriginalScopes(os)),
// generatedRanges: encodeGeneratedRanges(decoded.generatedRanges as GeneratedRange[]),
mappings: (0, import_sourcemap_codec.encode)(decoded.mappings)
});
}
function fromMap(input) {
const map = new import_trace_mapping.TraceMap(input);
const gen = new GenMapping({ file: map.file, sourceRoot: map.sourceRoot });
putAll(cast2(gen)._names, map.names);
putAll(cast2(gen)._sources, map.sources);
cast2(gen)._sourcesContent = map.sourcesContent || map.sources.map(() => null);
cast2(gen)._mappings = (0, import_trace_mapping.decodedMappings)(map);
if (map.ignoreList) putAll(cast2(gen)._ignoreList, map.ignoreList);
return gen;
}
function allMappings(map) {
const out = [];
const { _mappings: mappings, _sources: sources, _names: names } = cast2(map);
for (let i = 0; i < mappings.length; i++) {
const line = mappings[i];
for (let j = 0; j < line.length; j++) {
const seg = line[j];
const generated = { line: i + 1, column: seg[COLUMN] };
let source = void 0;
let original = void 0;
let name = void 0;
if (seg.length !== 1) {
source = sources.array[seg[SOURCES_INDEX]];
original = { line: seg[SOURCE_LINE] + 1, column: seg[SOURCE_COLUMN] };
if (seg.length === 5) name = names.array[seg[NAMES_INDEX]];
}
out.push({ generated, source, original, name });
}
}
return out;
}
function addSegmentInternal(skipable, map, genLine, genColumn, source, sourceLine, sourceColumn, name, content) {
const {
_mappings: mappings,
_sources: sources,
_sourcesContent: sourcesContent,
_names: names
// _originalScopes: originalScopes,
} = cast2(map);
const line = getIndex(mappings, genLine);
const index = getColumnIndex(line, genColumn);
if (!source) {
if (skipable && skipSourceless(line, index)) return;
return insert(line, index, [genColumn]);
}
assert(sourceLine);
assert(sourceColumn);
const sourcesIndex = put(sources, source);
const namesIndex = name ? put(names, name) : NO_NAME;
if (sourcesIndex === sourcesContent.length) sourcesContent[sourcesIndex] = content != null ? content : null;
if (skipable && skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex)) {
return;
}
return insert(
line,
index,
name ? [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex] : [genColumn, sourcesIndex, sourceLine, sourceColumn]
);
}
function assert(_val) {
}
function getIndex(arr, index) {
for (let i = arr.length; i <= index; i++) {
arr[i] = [];
}
return arr[index];
}
function getColumnIndex(line, genColumn) {
let index = line.length;
for (let i = index - 1; i >= 0; index = i--) {
const current = line[i];
if (genColumn >= current[COLUMN]) break;
}
return index;
}
function insert(array, index, value) {
for (let i = array.length; i > index; i--) {
array[i] = array[i - 1];
}
array[index] = value;
}
function removeEmptyFinalLines(mappings) {
const { length } = mappings;
let len = length;
for (let i = len - 1; i >= 0; len = i, i--) {
if (mappings[i].length > 0) break;
}
if (len < length) mappings.length = len;
}
function putAll(setarr, array) {
for (let i = 0; i < array.length; i++) put(setarr, array[i]);
}
function skipSourceless(line, index) {
if (index === 0) return true;
const prev = line[index - 1];
return prev.length === 1;
}
function skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex) {
if (index === 0) return false;
const prev = line[index - 1];
if (prev.length === 1) return false;
return sourcesIndex === prev[SOURCES_INDEX] && sourceLine === prev[SOURCE_LINE] && sourceColumn === prev[SOURCE_COLUMN] && namesIndex === (prev.length === 5 ? prev[NAMES_INDEX] : NO_NAME);
}
function addMappingInternal(skipable, map, mapping) {
const { generated, source, original, name, content } = mapping;
if (!source) {
return addSegmentInternal(
skipable,
map,
generated.line - 1,
generated.column,
null,
null,
null,
null,
null
);
}
assert(original);
return addSegmentInternal(
skipable,
map,
generated.line - 1,
generated.column,
source,
original.line - 1,
original.column,
name,
content
);
}
}));
//# sourceMappingURL=gen-mapping.umd.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,88 @@
import type { SourceMapInput } from '@jridgewell/trace-mapping';
import type { DecodedSourceMap, EncodedSourceMap, Pos, Mapping } from './types';
export type { DecodedSourceMap, EncodedSourceMap, Mapping };
export type Options = {
file?: string | null;
sourceRoot?: string | null;
};
/**
* Provides the state to generate a sourcemap.
*/
export declare class GenMapping {
private _names;
private _sources;
private _sourcesContent;
private _mappings;
private _ignoreList;
file: string | null | undefined;
sourceRoot: string | null | undefined;
constructor({ file, sourceRoot }?: Options);
}
/**
* A low-level API to associate a generated position with an original source position. Line and
* column here are 0-based, unlike `addMapping`.
*/
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source?: null, sourceLine?: null, sourceColumn?: null, name?: null, content?: null): void;
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source: string, sourceLine: number, sourceColumn: number, name?: null, content?: string | null): void;
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source: string, sourceLine: number, sourceColumn: number, name: string, content?: string | null): void;
/**
* A high-level API to associate a generated position with an original source position. Line is
* 1-based, but column is 0-based, due to legacy behavior in `source-map` library.
*/
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source?: null;
original?: null;
name?: null;
content?: null;
}): void;
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source: string;
original: Pos;
name?: null;
content?: string | null;
}): void;
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source: string;
original: Pos;
name: string;
content?: string | null;
}): void;
/**
* Same as `addSegment`, but will only add the segment if it generates useful information in the
* resulting map. This only works correctly if segments are added **in order**, meaning you should
* not add a segment with a lower generated line/column than one that came before.
*/
export declare const maybeAddSegment: typeof addSegment;
/**
* Same as `addMapping`, but will only add the mapping if it generates useful information in the
* resulting map. This only works correctly if mappings are added **in order**, meaning you should
* not add a mapping with a lower generated line/column than one that came before.
*/
export declare const maybeAddMapping: typeof addMapping;
/**
* Adds/removes the content of the source file to the source map.
*/
export declare function setSourceContent(map: GenMapping, source: string, content: string | null): void;
export declare function setIgnore(map: GenMapping, source: string, ignore?: boolean): void;
/**
* Returns a sourcemap object (with decoded mappings) suitable for passing to a library that expects
* a sourcemap, or to JSON.stringify.
*/
export declare function toDecodedMap(map: GenMapping): DecodedSourceMap;
/**
* Returns a sourcemap object (with encoded mappings) suitable for passing to a library that expects
* a sourcemap, or to JSON.stringify.
*/
export declare function toEncodedMap(map: GenMapping): EncodedSourceMap;
/**
* Constructs a new GenMapping, using the already present mappings of the input.
*/
export declare function fromMap(input: SourceMapInput): GenMapping;
/**
* Returns an array of high-level mapping objects for every recorded segment, which could then be
* passed to the `source-map` library.
*/
export declare function allMappings(map: GenMapping): Mapping[];

View File

@ -0,0 +1,32 @@
type Key = string | number | symbol;
/**
* SetArray acts like a `Set` (allowing only one occurrence of a string `key`), but provides the
* index of the `key` in the backing array.
*
* This is designed to allow synchronizing a second array with the contents of the backing array,
* like how in a sourcemap `sourcesContent[i]` is the source content associated with `source[i]`,
* and there are never duplicates.
*/
export declare class SetArray<T extends Key = Key> {
private _indexes;
array: readonly T[];
constructor();
}
/**
* Gets the index associated with `key` in the backing array, if it is already present.
*/
export declare function get<T extends Key>(setarr: SetArray<T>, key: T): number | undefined;
/**
* Puts `key` into the backing array, if it is not already present. Returns
* the index of the `key` in the backing array.
*/
export declare function put<T extends Key>(setarr: SetArray<T>, key: T): number;
/**
* Pops the last added item out of the SetArray.
*/
export declare function pop<T extends Key>(setarr: SetArray<T>): void;
/**
* Removes the key, if it exists in the set.
*/
export declare function remove<T extends Key>(setarr: SetArray<T>, key: T): void;
export {};

View File

@ -0,0 +1,12 @@
type GeneratedColumn = number;
type SourcesIndex = number;
type SourceLine = number;
type SourceColumn = number;
type NamesIndex = number;
export type SourceMapSegment = [GeneratedColumn] | [GeneratedColumn, SourcesIndex, SourceLine, SourceColumn] | [GeneratedColumn, SourcesIndex, SourceLine, SourceColumn, NamesIndex];
export declare const COLUMN = 0;
export declare const SOURCES_INDEX = 1;
export declare const SOURCE_LINE = 2;
export declare const SOURCE_COLUMN = 3;
export declare const NAMES_INDEX = 4;
export {};

View File

@ -0,0 +1,43 @@
import type { SourceMapSegment } from './sourcemap-segment';
export interface SourceMapV3 {
file?: string | null;
names: readonly string[];
sourceRoot?: string;
sources: readonly (string | null)[];
sourcesContent?: readonly (string | null)[];
version: 3;
ignoreList?: readonly number[];
}
export interface EncodedSourceMap extends SourceMapV3 {
mappings: string;
}
export interface DecodedSourceMap extends SourceMapV3 {
mappings: readonly SourceMapSegment[][];
}
export interface Pos {
line: number;
column: number;
}
export interface OriginalPos extends Pos {
source: string;
}
export interface BindingExpressionRange {
start: Pos;
expression: string;
}
export type Mapping = {
generated: Pos;
source: undefined;
original: undefined;
name: undefined;
} | {
generated: Pos;
source: string;
original: Pos;
name: string;
} | {
generated: Pos;
source: string;
original: Pos;
name: undefined;
};

67
node_modules/@jridgewell/gen-mapping/package.json generated vendored Normal file
View File

@ -0,0 +1,67 @@
{
"name": "@jridgewell/gen-mapping",
"version": "0.3.13",
"description": "Generate source maps",
"keywords": [
"source",
"map"
],
"main": "dist/gen-mapping.umd.js",
"module": "dist/gen-mapping.mjs",
"types": "types/gen-mapping.d.cts",
"files": [
"dist",
"src",
"types"
],
"exports": {
".": [
{
"import": {
"types": "./types/gen-mapping.d.mts",
"default": "./dist/gen-mapping.mjs"
},
"default": {
"types": "./types/gen-mapping.d.cts",
"default": "./dist/gen-mapping.umd.js"
}
},
"./dist/gen-mapping.umd.js"
],
"./package.json": "./package.json"
},
"scripts": {
"benchmark": "run-s build:code benchmark:*",
"benchmark:install": "cd benchmark && npm install",
"benchmark:only": "node --expose-gc benchmark/index.js",
"build": "run-s -n build:code build:types",
"build:code": "node ../../esbuild.mjs gen-mapping.ts",
"build:types": "run-s build:types:force build:types:emit build:types:mts",
"build:types:force": "rimraf tsconfig.build.tsbuildinfo",
"build:types:emit": "tsc --project tsconfig.build.json",
"build:types:mts": "node ../../mts-types.mjs",
"clean": "run-s -n clean:code clean:types",
"clean:code": "tsc --build --clean tsconfig.build.json",
"clean:types": "rimraf dist types",
"test": "run-s -n test:types test:only test:format",
"test:format": "prettier --check '{src,test}/**/*.ts'",
"test:only": "mocha",
"test:types": "eslint '{src,test}/**/*.ts'",
"lint": "run-s -n lint:types lint:format",
"lint:format": "npm run test:format -- --write",
"lint:types": "npm run test:types -- --fix",
"prepublishOnly": "npm run-s -n build test"
},
"homepage": "https://github.com/jridgewell/sourcemaps/tree/main/packages/gen-mapping",
"repository": {
"type": "git",
"url": "git+https://github.com/jridgewell/sourcemaps.git",
"directory": "packages/gen-mapping"
},
"author": "Justin Ridgewell <justin@ridgewell.name>",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
}

614
node_modules/@jridgewell/gen-mapping/src/gen-mapping.ts generated vendored Normal file
View File

@ -0,0 +1,614 @@
import { SetArray, put, remove } from './set-array';
import {
encode,
// encodeGeneratedRanges,
// encodeOriginalScopes
} from '@jridgewell/sourcemap-codec';
import { TraceMap, decodedMappings } from '@jridgewell/trace-mapping';
import {
COLUMN,
SOURCES_INDEX,
SOURCE_LINE,
SOURCE_COLUMN,
NAMES_INDEX,
} from './sourcemap-segment';
import type { SourceMapInput } from '@jridgewell/trace-mapping';
// import type { OriginalScope, GeneratedRange } from '@jridgewell/sourcemap-codec';
import type { SourceMapSegment } from './sourcemap-segment';
import type {
DecodedSourceMap,
EncodedSourceMap,
Pos,
Mapping,
// BindingExpressionRange,
// OriginalPos,
// OriginalScopeInfo,
// GeneratedRangeInfo,
} from './types';
export type { DecodedSourceMap, EncodedSourceMap, Mapping };
export type Options = {
file?: string | null;
sourceRoot?: string | null;
};
const NO_NAME = -1;
/**
* Provides the state to generate a sourcemap.
*/
export class GenMapping {
declare private _names: SetArray<string>;
declare private _sources: SetArray<string>;
declare private _sourcesContent: (string | null)[];
declare private _mappings: SourceMapSegment[][];
// private declare _originalScopes: OriginalScope[][];
// private declare _generatedRanges: GeneratedRange[];
declare private _ignoreList: SetArray<number>;
declare file: string | null | undefined;
declare sourceRoot: string | null | undefined;
constructor({ file, sourceRoot }: Options = {}) {
this._names = new SetArray();
this._sources = new SetArray();
this._sourcesContent = [];
this._mappings = [];
// this._originalScopes = [];
// this._generatedRanges = [];
this.file = file;
this.sourceRoot = sourceRoot;
this._ignoreList = new SetArray();
}
}
interface PublicMap {
_names: GenMapping['_names'];
_sources: GenMapping['_sources'];
_sourcesContent: GenMapping['_sourcesContent'];
_mappings: GenMapping['_mappings'];
// _originalScopes: GenMapping['_originalScopes'];
// _generatedRanges: GenMapping['_generatedRanges'];
_ignoreList: GenMapping['_ignoreList'];
}
/**
* Typescript doesn't allow friend access to private fields, so this just casts the map into a type
* with public access modifiers.
*/
function cast(map: unknown): PublicMap {
return map as any;
}
/**
* A low-level API to associate a generated position with an original source position. Line and
* column here are 0-based, unlike `addMapping`.
*/
export function addSegment(
map: GenMapping,
genLine: number,
genColumn: number,
source?: null,
sourceLine?: null,
sourceColumn?: null,
name?: null,
content?: null,
): void;
export function addSegment(
map: GenMapping,
genLine: number,
genColumn: number,
source: string,
sourceLine: number,
sourceColumn: number,
name?: null,
content?: string | null,
): void;
export function addSegment(
map: GenMapping,
genLine: number,
genColumn: number,
source: string,
sourceLine: number,
sourceColumn: number,
name: string,
content?: string | null,
): void;
export function addSegment(
map: GenMapping,
genLine: number,
genColumn: number,
source?: string | null,
sourceLine?: number | null,
sourceColumn?: number | null,
name?: string | null,
content?: string | null,
): void {
return addSegmentInternal(
false,
map,
genLine,
genColumn,
source,
sourceLine,
sourceColumn,
name,
content,
);
}
/**
* A high-level API to associate a generated position with an original source position. Line is
* 1-based, but column is 0-based, due to legacy behavior in `source-map` library.
*/
export function addMapping(
map: GenMapping,
mapping: {
generated: Pos;
source?: null;
original?: null;
name?: null;
content?: null;
},
): void;
export function addMapping(
map: GenMapping,
mapping: {
generated: Pos;
source: string;
original: Pos;
name?: null;
content?: string | null;
},
): void;
export function addMapping(
map: GenMapping,
mapping: {
generated: Pos;
source: string;
original: Pos;
name: string;
content?: string | null;
},
): void;
export function addMapping(
map: GenMapping,
mapping: {
generated: Pos;
source?: string | null;
original?: Pos | null;
name?: string | null;
content?: string | null;
},
): void {
return addMappingInternal(false, map, mapping as Parameters<typeof addMappingInternal>[2]);
}
/**
* Same as `addSegment`, but will only add the segment if it generates useful information in the
* resulting map. This only works correctly if segments are added **in order**, meaning you should
* not add a segment with a lower generated line/column than one that came before.
*/
export const maybeAddSegment: typeof addSegment = (
map,
genLine,
genColumn,
source,
sourceLine,
sourceColumn,
name,
content,
) => {
return addSegmentInternal(
true,
map,
genLine,
genColumn,
source,
sourceLine,
sourceColumn,
name,
content,
);
};
/**
* Same as `addMapping`, but will only add the mapping if it generates useful information in the
* resulting map. This only works correctly if mappings are added **in order**, meaning you should
* not add a mapping with a lower generated line/column than one that came before.
*/
export const maybeAddMapping: typeof addMapping = (map, mapping) => {
return addMappingInternal(true, map, mapping as Parameters<typeof addMappingInternal>[2]);
};
/**
* Adds/removes the content of the source file to the source map.
*/
export function setSourceContent(map: GenMapping, source: string, content: string | null): void {
const {
_sources: sources,
_sourcesContent: sourcesContent,
// _originalScopes: originalScopes,
} = cast(map);
const index = put(sources, source);
sourcesContent[index] = content;
// if (index === originalScopes.length) originalScopes[index] = [];
}
export function setIgnore(map: GenMapping, source: string, ignore = true) {
const {
_sources: sources,
_sourcesContent: sourcesContent,
_ignoreList: ignoreList,
// _originalScopes: originalScopes,
} = cast(map);
const index = put(sources, source);
if (index === sourcesContent.length) sourcesContent[index] = null;
// if (index === originalScopes.length) originalScopes[index] = [];
if (ignore) put(ignoreList, index);
else remove(ignoreList, index);
}
/**
* Returns a sourcemap object (with decoded mappings) suitable for passing to a library that expects
* a sourcemap, or to JSON.stringify.
*/
export function toDecodedMap(map: GenMapping): DecodedSourceMap {
const {
_mappings: mappings,
_sources: sources,
_sourcesContent: sourcesContent,
_names: names,
_ignoreList: ignoreList,
// _originalScopes: originalScopes,
// _generatedRanges: generatedRanges,
} = cast(map);
removeEmptyFinalLines(mappings);
return {
version: 3,
file: map.file || undefined,
names: names.array,
sourceRoot: map.sourceRoot || undefined,
sources: sources.array,
sourcesContent,
mappings,
// originalScopes,
// generatedRanges,
ignoreList: ignoreList.array,
};
}
/**
* Returns a sourcemap object (with encoded mappings) suitable for passing to a library that expects
* a sourcemap, or to JSON.stringify.
*/
export function toEncodedMap(map: GenMapping): EncodedSourceMap {
const decoded = toDecodedMap(map);
return Object.assign({}, decoded, {
// originalScopes: decoded.originalScopes.map((os) => encodeOriginalScopes(os)),
// generatedRanges: encodeGeneratedRanges(decoded.generatedRanges as GeneratedRange[]),
mappings: encode(decoded.mappings as SourceMapSegment[][]),
});
}
/**
* Constructs a new GenMapping, using the already present mappings of the input.
*/
export function fromMap(input: SourceMapInput): GenMapping {
const map = new TraceMap(input);
const gen = new GenMapping({ file: map.file, sourceRoot: map.sourceRoot });
putAll(cast(gen)._names, map.names);
putAll(cast(gen)._sources, map.sources as string[]);
cast(gen)._sourcesContent = map.sourcesContent || map.sources.map(() => null);
cast(gen)._mappings = decodedMappings(map) as GenMapping['_mappings'];
// TODO: implement originalScopes/generatedRanges
if (map.ignoreList) putAll(cast(gen)._ignoreList, map.ignoreList);
return gen;
}
/**
* Returns an array of high-level mapping objects for every recorded segment, which could then be
* passed to the `source-map` library.
*/
export function allMappings(map: GenMapping): Mapping[] {
const out: Mapping[] = [];
const { _mappings: mappings, _sources: sources, _names: names } = cast(map);
for (let i = 0; i < mappings.length; i++) {
const line = mappings[i];
for (let j = 0; j < line.length; j++) {
const seg = line[j];
const generated = { line: i + 1, column: seg[COLUMN] };
let source: string | undefined = undefined;
let original: Pos | undefined = undefined;
let name: string | undefined = undefined;
if (seg.length !== 1) {
source = sources.array[seg[SOURCES_INDEX]];
original = { line: seg[SOURCE_LINE] + 1, column: seg[SOURCE_COLUMN] };
if (seg.length === 5) name = names.array[seg[NAMES_INDEX]];
}
out.push({ generated, source, original, name } as Mapping);
}
}
return out;
}
// This split declaration is only so that terser can elminiate the static initialization block.
function addSegmentInternal<S extends string | null | undefined>(
skipable: boolean,
map: GenMapping,
genLine: number,
genColumn: number,
source: S,
sourceLine: S extends string ? number : null | undefined,
sourceColumn: S extends string ? number : null | undefined,
name: S extends string ? string | null | undefined : null | undefined,
content: S extends string ? string | null | undefined : null | undefined,
): void {
const {
_mappings: mappings,
_sources: sources,
_sourcesContent: sourcesContent,
_names: names,
// _originalScopes: originalScopes,
} = cast(map);
const line = getIndex(mappings, genLine);
const index = getColumnIndex(line, genColumn);
if (!source) {
if (skipable && skipSourceless(line, index)) return;
return insert(line, index, [genColumn]);
}
// Sigh, TypeScript can't figure out sourceLine and sourceColumn aren't nullish if source
// isn't nullish.
assert<number>(sourceLine);
assert<number>(sourceColumn);
const sourcesIndex = put(sources, source);
const namesIndex = name ? put(names, name) : NO_NAME;
if (sourcesIndex === sourcesContent.length) sourcesContent[sourcesIndex] = content ?? null;
// if (sourcesIndex === originalScopes.length) originalScopes[sourcesIndex] = [];
if (skipable && skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex)) {
return;
}
return insert(
line,
index,
name
? [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex]
: [genColumn, sourcesIndex, sourceLine, sourceColumn],
);
}
function assert<T>(_val: unknown): asserts _val is T {
// noop.
}
function getIndex<T>(arr: T[][], index: number): T[] {
for (let i = arr.length; i <= index; i++) {
arr[i] = [];
}
return arr[index];
}
function getColumnIndex(line: SourceMapSegment[], genColumn: number): number {
let index = line.length;
for (let i = index - 1; i >= 0; index = i--) {
const current = line[i];
if (genColumn >= current[COLUMN]) break;
}
return index;
}
function insert<T>(array: T[], index: number, value: T) {
for (let i = array.length; i > index; i--) {
array[i] = array[i - 1];
}
array[index] = value;
}
function removeEmptyFinalLines(mappings: SourceMapSegment[][]) {
const { length } = mappings;
let len = length;
for (let i = len - 1; i >= 0; len = i, i--) {
if (mappings[i].length > 0) break;
}
if (len < length) mappings.length = len;
}
function putAll<T extends string | number>(setarr: SetArray<T>, array: T[]) {
for (let i = 0; i < array.length; i++) put(setarr, array[i]);
}
function skipSourceless(line: SourceMapSegment[], index: number): boolean {
// The start of a line is already sourceless, so adding a sourceless segment to the beginning
// doesn't generate any useful information.
if (index === 0) return true;
const prev = line[index - 1];
// If the previous segment is also sourceless, then adding another sourceless segment doesn't
// genrate any new information. Else, this segment will end the source/named segment and point to
// a sourceless position, which is useful.
return prev.length === 1;
}
function skipSource(
line: SourceMapSegment[],
index: number,
sourcesIndex: number,
sourceLine: number,
sourceColumn: number,
namesIndex: number,
): boolean {
// A source/named segment at the start of a line gives position at that genColumn
if (index === 0) return false;
const prev = line[index - 1];
// If the previous segment is sourceless, then we're transitioning to a source.
if (prev.length === 1) return false;
// If the previous segment maps to the exact same source position, then this segment doesn't
// provide any new position information.
return (
sourcesIndex === prev[SOURCES_INDEX] &&
sourceLine === prev[SOURCE_LINE] &&
sourceColumn === prev[SOURCE_COLUMN] &&
namesIndex === (prev.length === 5 ? prev[NAMES_INDEX] : NO_NAME)
);
}
function addMappingInternal<S extends string | null | undefined>(
skipable: boolean,
map: GenMapping,
mapping: {
generated: Pos;
source: S;
original: S extends string ? Pos : null | undefined;
name: S extends string ? string | null | undefined : null | undefined;
content: S extends string ? string | null | undefined : null | undefined;
},
) {
const { generated, source, original, name, content } = mapping;
if (!source) {
return addSegmentInternal(
skipable,
map,
generated.line - 1,
generated.column,
null,
null,
null,
null,
null,
);
}
assert<Pos>(original);
return addSegmentInternal(
skipable,
map,
generated.line - 1,
generated.column,
source as string,
original.line - 1,
original.column,
name,
content,
);
}
/*
export function addOriginalScope(
map: GenMapping,
data: {
start: Pos;
end: Pos;
source: string;
kind: string;
name?: string;
variables?: string[];
},
): OriginalScopeInfo {
const { start, end, source, kind, name, variables } = data;
const {
_sources: sources,
_sourcesContent: sourcesContent,
_originalScopes: originalScopes,
_names: names,
} = cast(map);
const index = put(sources, source);
if (index === sourcesContent.length) sourcesContent[index] = null;
if (index === originalScopes.length) originalScopes[index] = [];
const kindIndex = put(names, kind);
const scope: OriginalScope = name
? [start.line - 1, start.column, end.line - 1, end.column, kindIndex, put(names, name)]
: [start.line - 1, start.column, end.line - 1, end.column, kindIndex];
if (variables) {
scope.vars = variables.map((v) => put(names, v));
}
const len = originalScopes[index].push(scope);
return [index, len - 1, variables];
}
*/
// Generated Ranges
/*
export function addGeneratedRange(
map: GenMapping,
data: {
start: Pos;
isScope: boolean;
originalScope?: OriginalScopeInfo;
callsite?: OriginalPos;
},
): GeneratedRangeInfo {
const { start, isScope, originalScope, callsite } = data;
const {
_originalScopes: originalScopes,
_sources: sources,
_sourcesContent: sourcesContent,
_generatedRanges: generatedRanges,
} = cast(map);
const range: GeneratedRange = [
start.line - 1,
start.column,
0,
0,
originalScope ? originalScope[0] : -1,
originalScope ? originalScope[1] : -1,
];
if (originalScope?.[2]) {
range.bindings = originalScope[2].map(() => [[-1]]);
}
if (callsite) {
const index = put(sources, callsite.source);
if (index === sourcesContent.length) sourcesContent[index] = null;
if (index === originalScopes.length) originalScopes[index] = [];
range.callsite = [index, callsite.line - 1, callsite.column];
}
if (isScope) range.isScope = true;
generatedRanges.push(range);
return [range, originalScope?.[2]];
}
export function setEndPosition(range: GeneratedRangeInfo, pos: Pos) {
range[0][2] = pos.line - 1;
range[0][3] = pos.column;
}
export function addBinding(
map: GenMapping,
range: GeneratedRangeInfo,
variable: string,
expression: string | BindingExpressionRange,
) {
const { _names: names } = cast(map);
const bindings = (range[0].bindings ||= []);
const vars = range[1];
const index = vars!.indexOf(variable);
const binding = getIndex(bindings, index);
if (typeof expression === 'string') binding[0] = [put(names, expression)];
else {
const { start } = expression;
binding.push([put(names, expression.expression), start.line - 1, start.column]);
}
}
*/

82
node_modules/@jridgewell/gen-mapping/src/set-array.ts generated vendored Normal file
View File

@ -0,0 +1,82 @@
type Key = string | number | symbol;
/**
* SetArray acts like a `Set` (allowing only one occurrence of a string `key`), but provides the
* index of the `key` in the backing array.
*
* This is designed to allow synchronizing a second array with the contents of the backing array,
* like how in a sourcemap `sourcesContent[i]` is the source content associated with `source[i]`,
* and there are never duplicates.
*/
export class SetArray<T extends Key = Key> {
declare private _indexes: Record<T, number | undefined>;
declare array: readonly T[];
constructor() {
this._indexes = { __proto__: null } as any;
this.array = [];
}
}
interface PublicSet<T extends Key> {
array: T[];
_indexes: SetArray<T>['_indexes'];
}
/**
* Typescript doesn't allow friend access to private fields, so this just casts the set into a type
* with public access modifiers.
*/
function cast<T extends Key>(set: SetArray<T>): PublicSet<T> {
return set as any;
}
/**
* Gets the index associated with `key` in the backing array, if it is already present.
*/
export function get<T extends Key>(setarr: SetArray<T>, key: T): number | undefined {
return cast(setarr)._indexes[key];
}
/**
* Puts `key` into the backing array, if it is not already present. Returns
* the index of the `key` in the backing array.
*/
export function put<T extends Key>(setarr: SetArray<T>, key: T): number {
// The key may or may not be present. If it is present, it's a number.
const index = get(setarr, key);
if (index !== undefined) return index;
const { array, _indexes: indexes } = cast(setarr);
const length = array.push(key);
return (indexes[key] = length - 1);
}
/**
* Pops the last added item out of the SetArray.
*/
export function pop<T extends Key>(setarr: SetArray<T>): void {
const { array, _indexes: indexes } = cast(setarr);
if (array.length === 0) return;
const last = array.pop()!;
indexes[last] = undefined;
}
/**
* Removes the key, if it exists in the set.
*/
export function remove<T extends Key>(setarr: SetArray<T>, key: T): void {
const index = get(setarr, key);
if (index === undefined) return;
const { array, _indexes: indexes } = cast(setarr);
for (let i = index + 1; i < array.length; i++) {
const k = array[i];
array[i - 1] = k;
indexes[k]!--;
}
indexes[key] = undefined;
array.pop();
}

View File

@ -0,0 +1,16 @@
type GeneratedColumn = number;
type SourcesIndex = number;
type SourceLine = number;
type SourceColumn = number;
type NamesIndex = number;
export type SourceMapSegment =
| [GeneratedColumn]
| [GeneratedColumn, SourcesIndex, SourceLine, SourceColumn]
| [GeneratedColumn, SourcesIndex, SourceLine, SourceColumn, NamesIndex];
export const COLUMN = 0;
export const SOURCES_INDEX = 1;
export const SOURCE_LINE = 2;
export const SOURCE_COLUMN = 3;
export const NAMES_INDEX = 4;

61
node_modules/@jridgewell/gen-mapping/src/types.ts generated vendored Normal file
View File

@ -0,0 +1,61 @@
// import type { GeneratedRange, OriginalScope } from '@jridgewell/sourcemap-codec';
import type { SourceMapSegment } from './sourcemap-segment';
export interface SourceMapV3 {
file?: string | null;
names: readonly string[];
sourceRoot?: string;
sources: readonly (string | null)[];
sourcesContent?: readonly (string | null)[];
version: 3;
ignoreList?: readonly number[];
}
export interface EncodedSourceMap extends SourceMapV3 {
mappings: string;
// originalScopes: string[];
// generatedRanges: string;
}
export interface DecodedSourceMap extends SourceMapV3 {
mappings: readonly SourceMapSegment[][];
// originalScopes: readonly OriginalScope[][];
// generatedRanges: readonly GeneratedRange[];
}
export interface Pos {
line: number; // 1-based
column: number; // 0-based
}
export interface OriginalPos extends Pos {
source: string;
}
export interface BindingExpressionRange {
start: Pos;
expression: string;
}
// export type OriginalScopeInfo = [number, number, string[] | undefined];
// export type GeneratedRangeInfo = [GeneratedRange, string[] | undefined];
export type Mapping =
| {
generated: Pos;
source: undefined;
original: undefined;
name: undefined;
}
| {
generated: Pos;
source: string;
original: Pos;
name: string;
}
| {
generated: Pos;
source: string;
original: Pos;
name: undefined;
};

View File

@ -0,0 +1,89 @@
import type { SourceMapInput } from '@jridgewell/trace-mapping';
import type { DecodedSourceMap, EncodedSourceMap, Pos, Mapping } from './types.cts';
export type { DecodedSourceMap, EncodedSourceMap, Mapping };
export type Options = {
file?: string | null;
sourceRoot?: string | null;
};
/**
* Provides the state to generate a sourcemap.
*/
export declare class GenMapping {
private _names;
private _sources;
private _sourcesContent;
private _mappings;
private _ignoreList;
file: string | null | undefined;
sourceRoot: string | null | undefined;
constructor({ file, sourceRoot }?: Options);
}
/**
* A low-level API to associate a generated position with an original source position. Line and
* column here are 0-based, unlike `addMapping`.
*/
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source?: null, sourceLine?: null, sourceColumn?: null, name?: null, content?: null): void;
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source: string, sourceLine: number, sourceColumn: number, name?: null, content?: string | null): void;
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source: string, sourceLine: number, sourceColumn: number, name: string, content?: string | null): void;
/**
* A high-level API to associate a generated position with an original source position. Line is
* 1-based, but column is 0-based, due to legacy behavior in `source-map` library.
*/
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source?: null;
original?: null;
name?: null;
content?: null;
}): void;
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source: string;
original: Pos;
name?: null;
content?: string | null;
}): void;
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source: string;
original: Pos;
name: string;
content?: string | null;
}): void;
/**
* Same as `addSegment`, but will only add the segment if it generates useful information in the
* resulting map. This only works correctly if segments are added **in order**, meaning you should
* not add a segment with a lower generated line/column than one that came before.
*/
export declare const maybeAddSegment: typeof addSegment;
/**
* Same as `addMapping`, but will only add the mapping if it generates useful information in the
* resulting map. This only works correctly if mappings are added **in order**, meaning you should
* not add a mapping with a lower generated line/column than one that came before.
*/
export declare const maybeAddMapping: typeof addMapping;
/**
* Adds/removes the content of the source file to the source map.
*/
export declare function setSourceContent(map: GenMapping, source: string, content: string | null): void;
export declare function setIgnore(map: GenMapping, source: string, ignore?: boolean): void;
/**
* Returns a sourcemap object (with decoded mappings) suitable for passing to a library that expects
* a sourcemap, or to JSON.stringify.
*/
export declare function toDecodedMap(map: GenMapping): DecodedSourceMap;
/**
* Returns a sourcemap object (with encoded mappings) suitable for passing to a library that expects
* a sourcemap, or to JSON.stringify.
*/
export declare function toEncodedMap(map: GenMapping): EncodedSourceMap;
/**
* Constructs a new GenMapping, using the already present mappings of the input.
*/
export declare function fromMap(input: SourceMapInput): GenMapping;
/**
* Returns an array of high-level mapping objects for every recorded segment, which could then be
* passed to the `source-map` library.
*/
export declare function allMappings(map: GenMapping): Mapping[];
//# sourceMappingURL=gen-mapping.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"gen-mapping.d.ts","sourceRoot":"","sources":["../src/gen-mapping.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,GAAG,EACH,OAAO,EAKR,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;AAE5D,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAIF;;GAEG;AACH,qBAAa,UAAU;IACrB,QAAgB,MAAM,CAAmB;IACzC,QAAgB,QAAQ,CAAmB;IAC3C,QAAgB,eAAe,CAAoB;IACnD,QAAgB,SAAS,CAAuB;IAGhD,QAAgB,WAAW,CAAmB;IACtC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;gBAElC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAE,OAAY;CAW/C;AAoBD;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,IAAI,EACb,UAAU,CAAC,EAAE,IAAI,EACjB,YAAY,CAAC,EAAE,IAAI,EACnB,IAAI,CAAC,EAAE,IAAI,EACX,OAAO,CAAC,EAAE,IAAI,GACb,IAAI,CAAC;AACR,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,IAAI,EACX,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GACtB,IAAI,CAAC;AACR,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GACtB,IAAI,CAAC;AAwBR;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE;IACP,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB,GACA,IAAI,CAAC;AACR,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE;IACP,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GACA,IAAI,CAAC;AACR,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE;IACP,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GACA,IAAI,CAAC;AAcR;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,UAqBpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,UAEpC,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAS9F;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAO,QAYvE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,gBAAgB,CAwB9D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,gBAAgB,CAO9D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,cAAc,GAAG,UAAU,CAYzD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,EAAE,CA0BtD"}

View File

@ -0,0 +1,89 @@
import type { SourceMapInput } from '@jridgewell/trace-mapping';
import type { DecodedSourceMap, EncodedSourceMap, Pos, Mapping } from './types.mts';
export type { DecodedSourceMap, EncodedSourceMap, Mapping };
export type Options = {
file?: string | null;
sourceRoot?: string | null;
};
/**
* Provides the state to generate a sourcemap.
*/
export declare class GenMapping {
private _names;
private _sources;
private _sourcesContent;
private _mappings;
private _ignoreList;
file: string | null | undefined;
sourceRoot: string | null | undefined;
constructor({ file, sourceRoot }?: Options);
}
/**
* A low-level API to associate a generated position with an original source position. Line and
* column here are 0-based, unlike `addMapping`.
*/
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source?: null, sourceLine?: null, sourceColumn?: null, name?: null, content?: null): void;
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source: string, sourceLine: number, sourceColumn: number, name?: null, content?: string | null): void;
export declare function addSegment(map: GenMapping, genLine: number, genColumn: number, source: string, sourceLine: number, sourceColumn: number, name: string, content?: string | null): void;
/**
* A high-level API to associate a generated position with an original source position. Line is
* 1-based, but column is 0-based, due to legacy behavior in `source-map` library.
*/
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source?: null;
original?: null;
name?: null;
content?: null;
}): void;
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source: string;
original: Pos;
name?: null;
content?: string | null;
}): void;
export declare function addMapping(map: GenMapping, mapping: {
generated: Pos;
source: string;
original: Pos;
name: string;
content?: string | null;
}): void;
/**
* Same as `addSegment`, but will only add the segment if it generates useful information in the
* resulting map. This only works correctly if segments are added **in order**, meaning you should
* not add a segment with a lower generated line/column than one that came before.
*/
export declare const maybeAddSegment: typeof addSegment;
/**
* Same as `addMapping`, but will only add the mapping if it generates useful information in the
* resulting map. This only works correctly if mappings are added **in order**, meaning you should
* not add a mapping with a lower generated line/column than one that came before.
*/
export declare const maybeAddMapping: typeof addMapping;
/**
* Adds/removes the content of the source file to the source map.
*/
export declare function setSourceContent(map: GenMapping, source: string, content: string | null): void;
export declare function setIgnore(map: GenMapping, source: string, ignore?: boolean): void;
/**
* Returns a sourcemap object (with decoded mappings) suitable for passing to a library that expects
* a sourcemap, or to JSON.stringify.
*/
export declare function toDecodedMap(map: GenMapping): DecodedSourceMap;
/**
* Returns a sourcemap object (with encoded mappings) suitable for passing to a library that expects
* a sourcemap, or to JSON.stringify.
*/
export declare function toEncodedMap(map: GenMapping): EncodedSourceMap;
/**
* Constructs a new GenMapping, using the already present mappings of the input.
*/
export declare function fromMap(input: SourceMapInput): GenMapping;
/**
* Returns an array of high-level mapping objects for every recorded segment, which could then be
* passed to the `source-map` library.
*/
export declare function allMappings(map: GenMapping): Mapping[];
//# sourceMappingURL=gen-mapping.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"gen-mapping.d.ts","sourceRoot":"","sources":["../src/gen-mapping.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,GAAG,EACH,OAAO,EAKR,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;AAE5D,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAIF;;GAEG;AACH,qBAAa,UAAU;IACrB,QAAgB,MAAM,CAAmB;IACzC,QAAgB,QAAQ,CAAmB;IAC3C,QAAgB,eAAe,CAAoB;IACnD,QAAgB,SAAS,CAAuB;IAGhD,QAAgB,WAAW,CAAmB;IACtC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;gBAElC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAE,OAAY;CAW/C;AAoBD;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,IAAI,EACb,UAAU,CAAC,EAAE,IAAI,EACjB,YAAY,CAAC,EAAE,IAAI,EACnB,IAAI,CAAC,EAAE,IAAI,EACX,OAAO,CAAC,EAAE,IAAI,GACb,IAAI,CAAC;AACR,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,IAAI,EACX,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GACtB,IAAI,CAAC;AACR,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GACtB,IAAI,CAAC;AAwBR;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE;IACP,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB,GACA,IAAI,CAAC;AACR,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE;IACP,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GACA,IAAI,CAAC;AACR,wBAAgB,UAAU,CACxB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE;IACP,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GACA,IAAI,CAAC;AAcR;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,UAqBpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,UAEpC,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAS9F;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAO,QAYvE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,gBAAgB,CAwB9D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,gBAAgB,CAO9D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,cAAc,GAAG,UAAU,CAYzD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,EAAE,CA0BtD"}

View File

@ -0,0 +1,33 @@
type Key = string | number | symbol;
/**
* SetArray acts like a `Set` (allowing only one occurrence of a string `key`), but provides the
* index of the `key` in the backing array.
*
* This is designed to allow synchronizing a second array with the contents of the backing array,
* like how in a sourcemap `sourcesContent[i]` is the source content associated with `source[i]`,
* and there are never duplicates.
*/
export declare class SetArray<T extends Key = Key> {
private _indexes;
array: readonly T[];
constructor();
}
/**
* Gets the index associated with `key` in the backing array, if it is already present.
*/
export declare function get<T extends Key>(setarr: SetArray<T>, key: T): number | undefined;
/**
* Puts `key` into the backing array, if it is not already present. Returns
* the index of the `key` in the backing array.
*/
export declare function put<T extends Key>(setarr: SetArray<T>, key: T): number;
/**
* Pops the last added item out of the SetArray.
*/
export declare function pop<T extends Key>(setarr: SetArray<T>): void;
/**
* Removes the key, if it exists in the set.
*/
export declare function remove<T extends Key>(setarr: SetArray<T>, key: T): void;
export {};
//# sourceMappingURL=set-array.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"set-array.d.ts","sourceRoot":"","sources":["../src/set-array.ts"],"names":[],"mappings":"AAAA,KAAK,GAAG,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpC;;;;;;;GAOG;AACH,qBAAa,QAAQ,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG;IACvC,QAAgB,QAAQ,CAAgC;IAChD,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;;CAM7B;AAeD;;GAEG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,SAAS,CAElF;AAED;;;GAGG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAStE;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAM5D;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAYvE"}

View File

@ -0,0 +1,33 @@
type Key = string | number | symbol;
/**
* SetArray acts like a `Set` (allowing only one occurrence of a string `key`), but provides the
* index of the `key` in the backing array.
*
* This is designed to allow synchronizing a second array with the contents of the backing array,
* like how in a sourcemap `sourcesContent[i]` is the source content associated with `source[i]`,
* and there are never duplicates.
*/
export declare class SetArray<T extends Key = Key> {
private _indexes;
array: readonly T[];
constructor();
}
/**
* Gets the index associated with `key` in the backing array, if it is already present.
*/
export declare function get<T extends Key>(setarr: SetArray<T>, key: T): number | undefined;
/**
* Puts `key` into the backing array, if it is not already present. Returns
* the index of the `key` in the backing array.
*/
export declare function put<T extends Key>(setarr: SetArray<T>, key: T): number;
/**
* Pops the last added item out of the SetArray.
*/
export declare function pop<T extends Key>(setarr: SetArray<T>): void;
/**
* Removes the key, if it exists in the set.
*/
export declare function remove<T extends Key>(setarr: SetArray<T>, key: T): void;
export {};
//# sourceMappingURL=set-array.d.ts.map

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