@rankcli/agent-runtime 0.0.29 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +249 -151
- package/dist/index.d.ts +249 -151
- package/dist/index.js +354 -302
- package/dist/index.mjs +351 -302
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -94,6 +94,7 @@ var RECIPES = {
|
|
|
94
94
|
jekyll: null,
|
|
95
95
|
eleventy: null,
|
|
96
96
|
pelican: null,
|
|
97
|
+
sphinx: null,
|
|
97
98
|
// Unknown
|
|
98
99
|
unknown: null
|
|
99
100
|
};
|
|
@@ -4210,234 +4211,156 @@ var ISSUE_DEFINITIONS = {
|
|
|
4210
4211
|
}
|
|
4211
4212
|
};
|
|
4212
4213
|
|
|
4213
|
-
// src/frameworks/
|
|
4214
|
-
var
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
},
|
|
4223
|
-
|
|
4224
|
-
{
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
},
|
|
4230
|
-
|
|
4231
|
-
{
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
},
|
|
4237
|
-
//
|
|
4238
|
-
{
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
},
|
|
4244
|
-
|
|
4245
|
-
{
|
|
4246
|
-
framework: "sveltekit",
|
|
4247
|
-
language: "typescript",
|
|
4248
|
-
patterns: [/__sveltekit/, /_app\/immutable/, /svelte-kit/],
|
|
4249
|
-
confidence: "high"
|
|
4250
|
-
},
|
|
4251
|
-
// Svelte (standalone)
|
|
4252
|
-
{
|
|
4253
|
-
framework: "svelte",
|
|
4254
|
-
language: "javascript",
|
|
4255
|
-
patterns: [/svelte-\w+/, /__svelte/],
|
|
4256
|
-
confidence: "medium"
|
|
4257
|
-
},
|
|
4258
|
-
// Remix
|
|
4259
|
-
{
|
|
4260
|
-
framework: "remix",
|
|
4261
|
-
language: "typescript",
|
|
4262
|
-
patterns: [/__remix/, /data-remix/],
|
|
4263
|
-
confidence: "high"
|
|
4264
|
-
},
|
|
4265
|
-
// Solid.js
|
|
4266
|
-
{
|
|
4267
|
-
framework: "solidjs",
|
|
4268
|
-
language: "typescript",
|
|
4269
|
-
patterns: [/data-solid/, /_solid/],
|
|
4270
|
-
confidence: "high"
|
|
4271
|
-
},
|
|
4272
|
-
// Qwik
|
|
4273
|
-
{
|
|
4274
|
-
framework: "qwik",
|
|
4275
|
-
language: "typescript",
|
|
4276
|
-
patterns: [/q:container/, /q:base/, /q:version/, /q:id=/, /qwik/],
|
|
4277
|
-
confidence: "high"
|
|
4278
|
-
},
|
|
4279
|
-
// Fresh (Deno)
|
|
4280
|
-
{
|
|
4281
|
-
framework: "fresh",
|
|
4282
|
-
language: "typescript",
|
|
4283
|
-
patterns: [/_frsh\//, /data-fresh/],
|
|
4284
|
-
confidence: "high"
|
|
4285
|
-
},
|
|
4286
|
-
// React (generic - lower priority)
|
|
4214
|
+
// src/frameworks/signals.ts
|
|
4215
|
+
var WEIGHT = { DECISIVE: 100, STRONG: 45, WEAK: 15 };
|
|
4216
|
+
var SCORE_FLOOR = 45;
|
|
4217
|
+
var SIGNALS = [
|
|
4218
|
+
// ---- Meta-frameworks: JavaScript ------------------------------------------------
|
|
4219
|
+
{ framework: "nextjs", language: "typescript", weight: WEIGHT.DECISIVE, name: "next-build-dir", html: /\/_next\/(static|image|data)\// },
|
|
4220
|
+
{ framework: "nextjs", language: "typescript", weight: WEIGHT.DECISIVE, name: "next-data", html: /__NEXT_DATA__|self\.__next_f/ },
|
|
4221
|
+
{ framework: "nextjs", language: "typescript", weight: WEIGHT.DECISIVE, name: "next-mount", html: /<div id=["']__next["']/ },
|
|
4222
|
+
{ framework: "nextjs", language: "typescript", weight: WEIGHT.DECISIVE, name: "next-powered-by", header: /^x-powered-by: next\.js/ },
|
|
4223
|
+
{ framework: "nuxt", language: "typescript", weight: WEIGHT.DECISIVE, name: "nuxt-build-dir", html: /\/_nuxt\// },
|
|
4224
|
+
{ framework: "nuxt", language: "typescript", weight: WEIGHT.DECISIVE, name: "nuxt-payload", html: /__NUXT__|__NUXT_DATA__|<div id="__nuxt"/ },
|
|
4225
|
+
{ framework: "nuxt", language: "typescript", weight: WEIGHT.DECISIVE, name: "nuxt-powered-by", header: /^x-powered-by: nuxt/ },
|
|
4226
|
+
{ framework: "astro", language: "typescript", weight: WEIGHT.DECISIVE, name: "astro-build-dir", html: /\/_astro\// },
|
|
4227
|
+
{ framework: "astro", language: "typescript", weight: WEIGHT.DECISIVE, name: "astro-island", html: /<astro-island|astro-slot|data-astro-(cid|source-file|transition)/ },
|
|
4228
|
+
{ framework: "astro", language: "typescript", weight: WEIGHT.STRONG, name: "astro-generator", html: /name=["']?generator["']?[^>]*content=["']?Astro/i },
|
|
4229
|
+
{ framework: "sveltekit", language: "typescript", weight: WEIGHT.DECISIVE, name: "sveltekit-immutable", html: /\/_app\/immutable\// },
|
|
4230
|
+
{ framework: "sveltekit", language: "typescript", weight: WEIGHT.DECISIVE, name: "sveltekit-runtime", html: /__sveltekit|kit\.start\(/ },
|
|
4231
|
+
{ framework: "remix", language: "typescript", weight: WEIGHT.DECISIVE, name: "remix-context", html: /__remixContext|__remixManifest|__remixRouteModules/ },
|
|
4232
|
+
{ framework: "remix", language: "typescript", weight: WEIGHT.STRONG, name: "remix-build-dir", html: /\/build\/_shared\/|\/build\/entry\.client-/ },
|
|
4233
|
+
{ framework: "gatsby", language: "javascript", weight: WEIGHT.DECISIVE, name: "gatsby-runtime", html: /___gatsby|window\.___chunkMapping/ },
|
|
4234
|
+
{ framework: "gatsby", language: "javascript", weight: WEIGHT.STRONG, name: "gatsby-page-data", html: /\/page-data\/(app-data\.json|sq\/)/ },
|
|
4235
|
+
{ framework: "qwik", language: "typescript", weight: WEIGHT.DECISIVE, name: "qwik-container", html: /q:container|q:base|q:version|qwikloader/ },
|
|
4236
|
+
{ framework: "fresh", language: "typescript", weight: WEIGHT.DECISIVE, name: "fresh-build-dir", html: /\/_frsh\// },
|
|
4237
|
+
{ framework: "solidjs", language: "typescript", weight: WEIGHT.STRONG, name: "solid-hydration", html: /_\$HY\b|data-hk=["']/ },
|
|
4238
|
+
// ---- Base UI libraries: weaker by nature, and that is the point -----------------
|
|
4239
|
+
{ framework: "angular", language: "typescript", weight: WEIGHT.DECISIVE, name: "angular-version", html: /ng-version=["']/ },
|
|
4240
|
+
{ framework: "angular", language: "typescript", weight: WEIGHT.DECISIVE, name: "angular-content-attr", html: /_ngcontent-|_nghost-/ },
|
|
4241
|
+
{ framework: "react", language: "javascript", weight: WEIGHT.STRONG, name: "react-root-marker", html: /data-reactroot|__reactContainer\$|__REACT_DEVTOOLS/ },
|
|
4242
|
+
// A Vite-built SPA: an empty mount point plus Vite's hashed entry bundle. Two weak facts
|
|
4243
|
+
// that together mean something; either one alone does not.
|
|
4244
|
+
{ framework: "react", language: "javascript", weight: WEIGHT.WEAK, name: "react-empty-root", html: /<div id="root"><\/div>/ },
|
|
4245
|
+
{ framework: "react", language: "javascript", weight: WEIGHT.WEAK, name: "react-refresh", html: /RefreshRuntime|react-refresh/ },
|
|
4287
4246
|
{
|
|
4288
4247
|
framework: "react",
|
|
4289
4248
|
language: "javascript",
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
//
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
{
|
|
4298
|
-
framework: "vue",
|
|
4299
|
-
language: "javascript",
|
|
4300
|
-
patterns: [/data-v-[a-f0-9]+/, /v-cloak/, /__vue/],
|
|
4301
|
-
confidence: "medium"
|
|
4302
|
-
},
|
|
4303
|
-
// Angular
|
|
4304
|
-
{
|
|
4305
|
-
framework: "angular",
|
|
4306
|
-
language: "typescript",
|
|
4307
|
-
patterns: [/ng-version/, /_ngcontent/, /ng-\w+=/, /\[ng/],
|
|
4308
|
-
confidence: "high"
|
|
4309
|
-
},
|
|
4310
|
-
// ============ Hypermedia Frameworks ============
|
|
4311
|
-
// HTMX
|
|
4312
|
-
{
|
|
4313
|
-
framework: "htmx",
|
|
4314
|
-
language: "unknown",
|
|
4315
|
-
patterns: [/hx-get/, /hx-post/, /hx-trigger/, /hx-swap/, /htmx\.org/],
|
|
4316
|
-
confidence: "high"
|
|
4317
|
-
},
|
|
4318
|
-
// Hotwire/Turbo
|
|
4319
|
-
{
|
|
4320
|
-
framework: "hotwire",
|
|
4321
|
-
language: "ruby",
|
|
4322
|
-
patterns: [/turbo-frame/, /turbo-stream/, /data-turbo/],
|
|
4323
|
-
confidence: "high"
|
|
4324
|
-
},
|
|
4325
|
-
// ============ PHP Frameworks ============
|
|
4326
|
-
// WordPress
|
|
4327
|
-
{
|
|
4328
|
-
framework: "wordpress",
|
|
4329
|
-
language: "php",
|
|
4330
|
-
// Technical signatures only. These patterns run over the whole page, so the old
|
|
4331
|
-
// /wordpress/i matched the word anywhere in the copy: rankcli.dev's own "detects
|
|
4332
|
-
// Rails, Django, Laravel, and WordPress" line was enough to detect its React SPA as
|
|
4333
|
-
// WordPress and then tell it to install an SEO plugin. A generator meta tag is the
|
|
4334
|
-
// one place the page says it about itself.
|
|
4335
|
-
patterns: [/wp-content/, /wp-includes/, /wp-json/, /name=["']generator["'][^>]*content=["']WordPress/i],
|
|
4336
|
-
confidence: "high"
|
|
4337
|
-
},
|
|
4338
|
-
// Laravel
|
|
4339
|
-
{
|
|
4340
|
-
framework: "laravel",
|
|
4341
|
-
language: "php",
|
|
4342
|
-
// /laravel/i had the same problem as WordPress above - it matched the word in prose.
|
|
4343
|
-
patterns: [/laravel_session/, /XSRF-TOKEN/, /@csrf/],
|
|
4344
|
-
confidence: "medium"
|
|
4345
|
-
},
|
|
4346
|
-
// Symfony
|
|
4347
|
-
{
|
|
4348
|
-
framework: "symfony",
|
|
4349
|
-
language: "php",
|
|
4350
|
-
// Likewise /symfony/, which matched any lowercase mention.
|
|
4351
|
-
patterns: [/sf2/, /_sf_/, /profiler\.css/],
|
|
4352
|
-
confidence: "medium"
|
|
4249
|
+
weight: WEIGHT.STRONG,
|
|
4250
|
+
name: "react-vite-spa",
|
|
4251
|
+
// Vite's entry chunk plus React's conventional mount point. Medium confidence by
|
|
4252
|
+
// construction: #app instead of #root stays unknown, because Vue, Solid and others use it.
|
|
4253
|
+
// Not `<div id="root"></div>`: a prerendered SPA has content inside its mount point, which
|
|
4254
|
+
// is what RankCLI's own site does and what the first version of this signal missed.
|
|
4255
|
+
allHtml: [/<script[^>]+src=["'][^"']+\.js["']/, /<div id="root"[\s>]/]
|
|
4353
4256
|
},
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
{
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
},
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
{
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
},
|
|
4370
|
-
|
|
4371
|
-
{
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
},
|
|
4377
|
-
|
|
4378
|
-
{
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
},
|
|
4384
|
-
|
|
4385
|
-
//
|
|
4386
|
-
{
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
},
|
|
4395
|
-
|
|
4396
|
-
//
|
|
4397
|
-
{
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
//
|
|
4404
|
-
//
|
|
4405
|
-
{
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
patterns: [/phx-/, /live-socket/, /data-phx/],
|
|
4409
|
-
confidence: "high"
|
|
4410
|
-
},
|
|
4411
|
-
// ============ Static Site Generators ============
|
|
4412
|
-
// Hugo
|
|
4413
|
-
{
|
|
4414
|
-
framework: "hugo",
|
|
4415
|
-
language: "go",
|
|
4416
|
-
patterns: [/name=["']generator["'][^>]*content=["']Hugo/i],
|
|
4417
|
-
confidence: "medium"
|
|
4418
|
-
},
|
|
4419
|
-
// Jekyll
|
|
4420
|
-
{
|
|
4421
|
-
framework: "jekyll",
|
|
4422
|
-
language: "ruby",
|
|
4423
|
-
patterns: [/name=["']generator["'][^>]*content=["']Jekyll/i],
|
|
4424
|
-
confidence: "medium"
|
|
4425
|
-
},
|
|
4426
|
-
// Eleventy
|
|
4427
|
-
{
|
|
4428
|
-
framework: "eleventy",
|
|
4429
|
-
language: "javascript",
|
|
4430
|
-
patterns: [/11ty/, /eleventy/, /generator.*eleventy/i],
|
|
4431
|
-
confidence: "medium"
|
|
4432
|
-
},
|
|
4433
|
-
// Pelican
|
|
4434
|
-
{
|
|
4435
|
-
framework: "pelican",
|
|
4436
|
-
language: "python",
|
|
4437
|
-
patterns: [/pelican/, /generator.*pelican/i],
|
|
4438
|
-
confidence: "medium"
|
|
4439
|
-
}
|
|
4257
|
+
{ framework: "vue", language: "javascript", weight: WEIGHT.DECISIVE, name: "vitepress-runtime", html: /__VP_HASH_MAP__|__VP_SITE_DATA__/ },
|
|
4258
|
+
{ framework: "vue", language: "javascript", weight: WEIGHT.DECISIVE, name: "vue-scoped-style", html: /data-v-[0-9a-f]{6,10}\b/ },
|
|
4259
|
+
{ framework: "vue", language: "javascript", weight: WEIGHT.WEAK, name: "vue-cloak", html: /v-cloak|<div id="app"><\/div>/ },
|
|
4260
|
+
{ framework: "svelte", language: "javascript", weight: WEIGHT.WEAK, name: "svelte-class", html: /class=["'][^"']*svelte-[0-9a-z]{6}/ },
|
|
4261
|
+
// ---- Ruby -----------------------------------------------------------------------
|
|
4262
|
+
// csrf-token alone is emitted by Rails, Laravel, Phoenix and Django. csrf-param is Rails.
|
|
4263
|
+
{ framework: "rails", language: "ruby", weight: WEIGHT.DECISIVE, name: "rails-csrf-param", html: /name=["']csrf-param["']/ },
|
|
4264
|
+
{ framework: "rails", language: "ruby", weight: WEIGHT.STRONG, name: "rails-ujs", html: /rails-ujs|turbolinks|data-remote=["']true["']|action_cable|actioncable/ },
|
|
4265
|
+
{ framework: "rails", language: "ruby", weight: WEIGHT.STRONG, name: "rails-session-cookie", header: /^set-cookie: [^;]*_session=/ },
|
|
4266
|
+
{ framework: "rails", language: "ruby", weight: WEIGHT.STRONG, name: "rails-app-server", header: /^(server|x-powered-by): (puma|passenger|unicorn|phusion)/ },
|
|
4267
|
+
{ framework: "hotwire", language: "ruby", weight: WEIGHT.STRONG, name: "turbo-elements", html: /<turbo-frame|<turbo-stream|data-turbo-track/ },
|
|
4268
|
+
// ---- Python ---------------------------------------------------------------------
|
|
4269
|
+
{ framework: "django", language: "python", weight: WEIGHT.DECISIVE, name: "django-csrf-input", html: /name=["']csrfmiddlewaretoken["']/ },
|
|
4270
|
+
{ framework: "django", language: "python", weight: WEIGHT.DECISIVE, name: "django-csrf-cookie", header: /^set-cookie: csrftoken=/ },
|
|
4271
|
+
{ framework: "django", language: "python", weight: WEIGHT.STRONG, name: "django-admin-static", html: /\/static\/admin\/(css|js)\// },
|
|
4272
|
+
{ framework: "django", language: "python", weight: WEIGHT.WEAK, name: "django-wsgi-server", header: /^(server|x-powered-by): (gunicorn|uvicorn|daphne)/ },
|
|
4273
|
+
{ framework: "flask", language: "python", weight: WEIGHT.STRONG, name: "flask-server", header: /^server: werkzeug/ },
|
|
4274
|
+
{ framework: "fastapi", language: "python", weight: WEIGHT.STRONG, name: "fastapi-docs", html: /swagger-ui-bundle\.js[\s\S]{0,200}openapi\.json/ },
|
|
4275
|
+
// ---- PHP ------------------------------------------------------------------------
|
|
4276
|
+
{ framework: "wordpress", language: "php", weight: WEIGHT.DECISIVE, name: "wp-paths", html: /\/wp-content\/|\/wp-includes\/|\/wp-json\// },
|
|
4277
|
+
{ framework: "wordpress", language: "php", weight: WEIGHT.DECISIVE, name: "wp-generator", html: /name=["']?generator["']?[^>]*content=["']?WordPress/i },
|
|
4278
|
+
{ framework: "wordpress", language: "php", weight: WEIGHT.STRONG, name: "wp-powered-by", header: /^x-powered-by: wordpress/ },
|
|
4279
|
+
{ framework: "laravel", language: "php", weight: WEIGHT.DECISIVE, name: "laravel-session-cookie", header: /^set-cookie: laravel_session=/ },
|
|
4280
|
+
{ framework: "laravel", language: "php", weight: WEIGHT.STRONG, name: "laravel-xsrf-cookie", header: /^set-cookie: XSRF-TOKEN=/i },
|
|
4281
|
+
{ framework: "laravel", language: "php", weight: WEIGHT.STRONG, name: "laravel-livewire", html: /livewire|wire:(click|model|submit)/i },
|
|
4282
|
+
{ framework: "laravel", language: "php", weight: WEIGHT.WEAK, name: "laravel-vite-build", html: /\/build\/assets\/app-[A-Za-z0-9_-]{8}\.js/ },
|
|
4283
|
+
{ framework: "symfony", language: "php", weight: WEIGHT.DECISIVE, name: "symfony-profiler", html: /\/_profiler\/|sf-toolbar|sf-dump/ },
|
|
4284
|
+
{ framework: "symfony", language: "php", weight: WEIGHT.STRONG, name: "symfony-cookie", header: /^set-cookie: (sfsession|symfony)/i },
|
|
4285
|
+
// ---- Elixir ---------------------------------------------------------------------
|
|
4286
|
+
{ framework: "phoenix", language: "elixir", weight: WEIGHT.DECISIVE, name: "phoenix-liveview", html: /phx-(click|submit|change|value|hook|socket|main|track-static)/ },
|
|
4287
|
+
{ framework: "phoenix", language: "elixir", weight: WEIGHT.STRONG, name: "phoenix-cowboy", header: /^server: cowboy/ },
|
|
4288
|
+
// ---- Java / C# / Go -------------------------------------------------------------
|
|
4289
|
+
{ framework: "spring", language: "java", weight: WEIGHT.STRONG, name: "thymeleaf-attr", html: /\sth:[a-z-]+=/ },
|
|
4290
|
+
{ framework: "spring", language: "java", weight: WEIGHT.STRONG, name: "spring-server", header: /^server: (apache-coyote|tomcat|jetty)/ },
|
|
4291
|
+
{ framework: "aspnet", language: "csharp", weight: WEIGHT.DECISIVE, name: "aspnet-verification-token", html: /__RequestVerificationToken|__VIEWSTATE/ },
|
|
4292
|
+
{ framework: "aspnet", language: "csharp", weight: WEIGHT.STRONG, name: "aspnet-server", header: /^(server: kestrel|x-powered-by: asp\.net|x-aspnet-version:)/ },
|
|
4293
|
+
// "gin" used to be tested as a substring of the Server header, which matches nginx - the
|
|
4294
|
+
// single most common web server there is. Anchored to the whole value now.
|
|
4295
|
+
{ framework: "go", language: "go", weight: WEIGHT.STRONG, name: "go-server", header: /^server: (gin|echo|fiber|gorilla)(\/|$| )/ },
|
|
4296
|
+
// ---- Hypermedia -----------------------------------------------------------------
|
|
4297
|
+
{ framework: "htmx", language: "unknown", weight: WEIGHT.STRONG, name: "htmx-attrs", html: /\shx-(get|post|put|delete|trigger|swap|target)=/ },
|
|
4298
|
+
{ framework: "htmx", language: "unknown", weight: WEIGHT.DECISIVE, name: "htmx-script", html: /htmx(\.min)?\.js|unpkg\.com\/htmx/ },
|
|
4299
|
+
// ---- Static site generators: they announce themselves -----------------------------
|
|
4300
|
+
{ framework: "hugo", language: "go", weight: WEIGHT.DECISIVE, name: "hugo-generator", html: /name=["']?generator["']?[^>]*content=["']?Hugo/i },
|
|
4301
|
+
{ framework: "hugo", language: "go", weight: WEIGHT.STRONG, name: "hugo-generator-header", header: /^x-generator: hugo/ },
|
|
4302
|
+
{ framework: "jekyll", language: "ruby", weight: WEIGHT.DECISIVE, name: "jekyll-generator", html: /name=["']?generator["']?[^>]*content=["']?Jekyll/i },
|
|
4303
|
+
{ framework: "eleventy", language: "javascript", weight: WEIGHT.DECISIVE, name: "eleventy-generator", html: /name=["']?generator["']?[^>]*content=["']?Eleventy/i },
|
|
4304
|
+
{ framework: "pelican", language: "python", weight: WEIGHT.DECISIVE, name: "pelican-generator", html: /name=["']?generator["']?[^>]*content=["']?Pelican/i },
|
|
4305
|
+
// Sphinx: what nearly every Python project's documentation is built with, and the shape
|
|
4306
|
+
// flask.palletsprojects.com turned out to be. Structural markers only - not the word
|
|
4307
|
+
// "sphinx", which appears in plenty of prose.
|
|
4308
|
+
{ framework: "sphinx", language: "python", weight: WEIGHT.DECISIVE, name: "sphinx-doc-options", html: /_static\/documentation_options\.js/ },
|
|
4309
|
+
{ framework: "sphinx", language: "python", weight: WEIGHT.STRONG, name: "sphinx-theme-markup", html: /class=["'][^"']*sphinxsidebar|sphinx-highlight|_static\/searchtools\.js/ },
|
|
4310
|
+
{ framework: "sphinx", language: "python", weight: WEIGHT.STRONG, name: "docutils-generator", html: /name=["']?generator["']?[^>]*content=["']?Docutils/i }
|
|
4440
4311
|
];
|
|
4312
|
+
function headerLines(headers) {
|
|
4313
|
+
if (!headers) return "";
|
|
4314
|
+
return Object.entries(headers).map(([k, v]) => `${k.toLowerCase()}: ${String(v).toLowerCase()}`).join("\n");
|
|
4315
|
+
}
|
|
4316
|
+
function detectFromEvidence(input) {
|
|
4317
|
+
const html = input.html ?? "";
|
|
4318
|
+
const headers = headerLines(input.headers);
|
|
4319
|
+
const byFramework = /* @__PURE__ */ new Map();
|
|
4320
|
+
for (const signal of SIGNALS) {
|
|
4321
|
+
const headerHit = signal.header && headers && new RegExp(
|
|
4322
|
+
signal.header.source,
|
|
4323
|
+
signal.header.flags.includes("m") ? signal.header.flags : `${signal.header.flags}m`
|
|
4324
|
+
).test(headers);
|
|
4325
|
+
const allHit = signal.allHtml && html && signal.allHtml.every((re) => re.test(html));
|
|
4326
|
+
const hit = signal.html && html && signal.html.test(html) || headerHit || allHit;
|
|
4327
|
+
if (!hit) continue;
|
|
4328
|
+
const existing = byFramework.get(signal.framework);
|
|
4329
|
+
if (existing) {
|
|
4330
|
+
existing.score += signal.weight;
|
|
4331
|
+
existing.matched.push(signal.name);
|
|
4332
|
+
} else {
|
|
4333
|
+
byFramework.set(signal.framework, {
|
|
4334
|
+
framework: signal.framework,
|
|
4335
|
+
language: signal.language,
|
|
4336
|
+
score: signal.weight,
|
|
4337
|
+
matched: [signal.name]
|
|
4338
|
+
});
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
const ranked = [...byFramework.values()].sort((a, b) => b.score - a.score || a.framework.localeCompare(b.framework));
|
|
4342
|
+
const best = ranked[0];
|
|
4343
|
+
if (!best || best.score < SCORE_FLOOR) {
|
|
4344
|
+
return {
|
|
4345
|
+
framework: "unknown",
|
|
4346
|
+
language: "unknown",
|
|
4347
|
+
confidence: "low",
|
|
4348
|
+
score: best?.score ?? 0,
|
|
4349
|
+
matched: best?.matched ?? [],
|
|
4350
|
+
alternatives: ranked
|
|
4351
|
+
};
|
|
4352
|
+
}
|
|
4353
|
+
return {
|
|
4354
|
+
framework: best.framework,
|
|
4355
|
+
language: best.language,
|
|
4356
|
+
confidence: best.score >= WEIGHT.DECISIVE ? "high" : "medium",
|
|
4357
|
+
score: best.score,
|
|
4358
|
+
matched: best.matched,
|
|
4359
|
+
alternatives: ranked.slice(1)
|
|
4360
|
+
};
|
|
4361
|
+
}
|
|
4362
|
+
|
|
4363
|
+
// src/frameworks/detector.ts
|
|
4441
4364
|
var PACKAGE_DEPENDENCIES = [
|
|
4442
4365
|
// Meta-frameworks (check first - more specific)
|
|
4443
4366
|
{ framework: "nextjs", language: "typescript", packages: ["next"], meta_framework: "react" },
|
|
@@ -4487,19 +4410,14 @@ var ELIXIR_DEPENDENCIES = [
|
|
|
4487
4410
|
{ framework: "phoenix", language: "elixir", packages: [":phoenix", "phoenix"] }
|
|
4488
4411
|
];
|
|
4489
4412
|
function detectFromHtml(html) {
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
};
|
|
4499
|
-
}
|
|
4500
|
-
}
|
|
4501
|
-
}
|
|
4502
|
-
return null;
|
|
4413
|
+
const result = detectFromEvidence({ html });
|
|
4414
|
+
if (result.framework === "unknown") return null;
|
|
4415
|
+
return {
|
|
4416
|
+
framework: result.framework,
|
|
4417
|
+
language: result.language,
|
|
4418
|
+
confidence: result.confidence,
|
|
4419
|
+
detected_from: "html"
|
|
4420
|
+
};
|
|
4503
4421
|
}
|
|
4504
4422
|
function detectFromPackageJson(packageJson) {
|
|
4505
4423
|
const allDeps = {
|
|
@@ -4641,52 +4559,14 @@ function detectFromMixExs(mixContent) {
|
|
|
4641
4559
|
return null;
|
|
4642
4560
|
}
|
|
4643
4561
|
function detectFromHeaders(headers) {
|
|
4644
|
-
const
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
}
|
|
4653
|
-
if (poweredBy.includes("remix")) {
|
|
4654
|
-
return { framework: "remix", language: "typescript", confidence: "high", detected_from: "headers" };
|
|
4655
|
-
}
|
|
4656
|
-
if (poweredBy.includes("phusion") || poweredBy.includes("passenger") || poweredBy.includes("puma") || poweredBy.includes("unicorn")) {
|
|
4657
|
-
return { framework: "rails", language: "ruby", confidence: "medium", detected_from: "headers" };
|
|
4658
|
-
}
|
|
4659
|
-
if (poweredBy.includes("gunicorn") || poweredBy.includes("uvicorn") || poweredBy.includes("daphne")) {
|
|
4660
|
-
return null;
|
|
4661
|
-
}
|
|
4662
|
-
if (poweredBy.includes("php")) {
|
|
4663
|
-
return null;
|
|
4664
|
-
}
|
|
4665
|
-
if (server.includes("tomcat") || server.includes("jetty") || poweredBy.includes("spring")) {
|
|
4666
|
-
return { framework: "spring", language: "java", confidence: "medium", detected_from: "headers" };
|
|
4667
|
-
}
|
|
4668
|
-
if (poweredBy.includes("asp.net") || server.includes("kestrel")) {
|
|
4669
|
-
return { framework: "aspnet", language: "csharp", confidence: "high", detected_from: "headers" };
|
|
4670
|
-
}
|
|
4671
|
-
if (poweredBy.includes("phoenix") || poweredBy.includes("cowboy")) {
|
|
4672
|
-
return { framework: "phoenix", language: "elixir", confidence: "medium", detected_from: "headers" };
|
|
4673
|
-
}
|
|
4674
|
-
if (server.includes("gin") || server.includes("echo") || server.includes("fiber")) {
|
|
4675
|
-
return { framework: "go", language: "go", confidence: "medium", detected_from: "headers" };
|
|
4676
|
-
}
|
|
4677
|
-
if (generator.includes("hugo")) {
|
|
4678
|
-
return { framework: "hugo", language: "go", confidence: "high", detected_from: "headers" };
|
|
4679
|
-
}
|
|
4680
|
-
if (generator.includes("jekyll")) {
|
|
4681
|
-
return { framework: "jekyll", language: "ruby", confidence: "high", detected_from: "headers" };
|
|
4682
|
-
}
|
|
4683
|
-
if (generator.includes("eleventy") || generator.includes("11ty")) {
|
|
4684
|
-
return { framework: "eleventy", language: "javascript", confidence: "high", detected_from: "headers" };
|
|
4685
|
-
}
|
|
4686
|
-
if (generator.includes("pelican")) {
|
|
4687
|
-
return { framework: "pelican", language: "python", confidence: "high", detected_from: "headers" };
|
|
4688
|
-
}
|
|
4689
|
-
return null;
|
|
4562
|
+
const result = detectFromEvidence({ headers });
|
|
4563
|
+
if (result.framework === "unknown") return null;
|
|
4564
|
+
return {
|
|
4565
|
+
framework: result.framework,
|
|
4566
|
+
language: result.language,
|
|
4567
|
+
confidence: result.confidence,
|
|
4568
|
+
detected_from: "headers"
|
|
4569
|
+
};
|
|
4690
4570
|
}
|
|
4691
4571
|
function detectFramework(options) {
|
|
4692
4572
|
if (options.packageJson) {
|
|
@@ -4721,13 +4601,16 @@ function detectFramework(options) {
|
|
|
4721
4601
|
const result = detectFromMixExs(options.mixExsContent);
|
|
4722
4602
|
if (result) return result;
|
|
4723
4603
|
}
|
|
4724
|
-
if (options.headers) {
|
|
4725
|
-
const result =
|
|
4726
|
-
if (result)
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4604
|
+
if (options.html || options.headers) {
|
|
4605
|
+
const result = detectFromEvidence({ html: options.html, headers: options.headers });
|
|
4606
|
+
if (result.framework !== "unknown") {
|
|
4607
|
+
return {
|
|
4608
|
+
framework: result.framework,
|
|
4609
|
+
language: result.language,
|
|
4610
|
+
confidence: result.confidence,
|
|
4611
|
+
detected_from: options.html ? "html" : "headers"
|
|
4612
|
+
};
|
|
4613
|
+
}
|
|
4731
4614
|
}
|
|
4732
4615
|
if (options.files) {
|
|
4733
4616
|
if (options.files.some((f) => f.includes("next.config"))) {
|
|
@@ -4834,6 +4717,7 @@ function getFrameworkDisplayName(framework) {
|
|
|
4834
4717
|
jekyll: "Jekyll",
|
|
4835
4718
|
eleventy: "Eleventy (11ty)",
|
|
4836
4719
|
pelican: "Pelican",
|
|
4720
|
+
sphinx: "Sphinx",
|
|
4837
4721
|
unknown: "Unknown"
|
|
4838
4722
|
};
|
|
4839
4723
|
return names[framework];
|
|
@@ -9199,20 +9083,20 @@ function findMissingPreconnects(thirdPartyDomains, existingHints) {
|
|
|
9199
9083
|
}
|
|
9200
9084
|
})
|
|
9201
9085
|
);
|
|
9202
|
-
const
|
|
9086
|
+
const missing2 = [];
|
|
9203
9087
|
for (const domain of thirdPartyDomains) {
|
|
9204
9088
|
try {
|
|
9205
9089
|
const hostname = new URL(domain).hostname;
|
|
9206
9090
|
const recommended = CRITICAL_THIRD_PARTIES[hostname] || [domain];
|
|
9207
9091
|
for (const rec of recommended) {
|
|
9208
9092
|
if (!preconnected.has(rec)) {
|
|
9209
|
-
|
|
9093
|
+
missing2.push(rec);
|
|
9210
9094
|
}
|
|
9211
9095
|
}
|
|
9212
9096
|
} catch {
|
|
9213
9097
|
}
|
|
9214
9098
|
}
|
|
9215
|
-
return [...new Set(
|
|
9099
|
+
return [...new Set(missing2)];
|
|
9216
9100
|
}
|
|
9217
9101
|
function analyzeResourceHints(html, url) {
|
|
9218
9102
|
const issues = [];
|
|
@@ -29481,6 +29365,167 @@ function findAppRoot(files) {
|
|
|
29481
29365
|
return `${nonRoot[0]}/`;
|
|
29482
29366
|
}
|
|
29483
29367
|
|
|
29368
|
+
// src/fixer/safety.ts
|
|
29369
|
+
var HTML_EXT = /\.html?$/i;
|
|
29370
|
+
var SOURCE_EXT = /\.(ts|tsx|js|jsx|mjs|cjs|vue|svelte|astro)$/i;
|
|
29371
|
+
function attributeValues(html, pattern) {
|
|
29372
|
+
const found = /* @__PURE__ */ new Set();
|
|
29373
|
+
for (const match of html.matchAll(pattern)) {
|
|
29374
|
+
const value = match[1]?.trim();
|
|
29375
|
+
if (value) found.add(value);
|
|
29376
|
+
}
|
|
29377
|
+
return found;
|
|
29378
|
+
}
|
|
29379
|
+
function scriptSources(html) {
|
|
29380
|
+
return attributeValues(html, /<script[^>]+src=["']([^"']+)["']/gi);
|
|
29381
|
+
}
|
|
29382
|
+
function stylesheetHrefs(html) {
|
|
29383
|
+
return attributeValues(html, /<link[^>]+href=["']([^"']+)["'][^>]*>/gi);
|
|
29384
|
+
}
|
|
29385
|
+
function verificationTokens(html) {
|
|
29386
|
+
const found = /* @__PURE__ */ new Set();
|
|
29387
|
+
for (const match of html.matchAll(/<meta[^>]+name=["']([^"']*(?:site-verification|verify|verification)[^"']*)["'][^>]*>/gi)) {
|
|
29388
|
+
found.add(match[1].toLowerCase());
|
|
29389
|
+
}
|
|
29390
|
+
return found;
|
|
29391
|
+
}
|
|
29392
|
+
function importSpecifiers(source) {
|
|
29393
|
+
const found = /* @__PURE__ */ new Set();
|
|
29394
|
+
for (const match of source.matchAll(/\bfrom\s+["']([^"']+)["']/g)) found.add(match[1]);
|
|
29395
|
+
for (const match of source.matchAll(/\brequire\(\s*["']([^"']+)["']\s*\)/g)) found.add(match[1]);
|
|
29396
|
+
return found;
|
|
29397
|
+
}
|
|
29398
|
+
function missing(before, after) {
|
|
29399
|
+
return [...before].filter((value) => !after.has(value));
|
|
29400
|
+
}
|
|
29401
|
+
function xmlConcern(xml) {
|
|
29402
|
+
const stack = [];
|
|
29403
|
+
for (const match of xml.matchAll(/<\/?([A-Za-z_][\w:.-]*)[^>]*?(\/?)>/g)) {
|
|
29404
|
+
const [tag, name, selfClosing] = match;
|
|
29405
|
+
if (tag.startsWith("<?") || tag.startsWith("<!")) continue;
|
|
29406
|
+
if (tag.startsWith("</")) {
|
|
29407
|
+
if (stack.pop() !== name) return `unbalanced </${name}>`;
|
|
29408
|
+
} else if (!selfClosing) {
|
|
29409
|
+
stack.push(name);
|
|
29410
|
+
}
|
|
29411
|
+
}
|
|
29412
|
+
return stack.length ? `unclosed <${stack[stack.length - 1]}>` : null;
|
|
29413
|
+
}
|
|
29414
|
+
function sitemapUrlCount(xml) {
|
|
29415
|
+
return [...xml.matchAll(/<loc>/gi)].length;
|
|
29416
|
+
}
|
|
29417
|
+
function newestLastmod(xml) {
|
|
29418
|
+
const dates = [...xml.matchAll(/<lastmod>([^<]+)<\/lastmod>/gi)].map((m) => Date.parse(m[1].trim())).filter((t) => !Number.isNaN(t));
|
|
29419
|
+
return dates.length ? Math.max(...dates) : null;
|
|
29420
|
+
}
|
|
29421
|
+
function jsonLdConcerns(html) {
|
|
29422
|
+
const bad = [];
|
|
29423
|
+
for (const match of html.matchAll(/<script[^>]+type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/gi)) {
|
|
29424
|
+
try {
|
|
29425
|
+
JSON.parse(match[1]);
|
|
29426
|
+
} catch (error) {
|
|
29427
|
+
bad.push(error.message);
|
|
29428
|
+
}
|
|
29429
|
+
}
|
|
29430
|
+
return bad;
|
|
29431
|
+
}
|
|
29432
|
+
function assessReplacement(path3, original, replacement) {
|
|
29433
|
+
const concerns = [];
|
|
29434
|
+
const add = (code, detail) => concerns.push({ code, detail });
|
|
29435
|
+
if (/\.json$/i.test(path3) || /\.webmanifest$/i.test(path3)) {
|
|
29436
|
+
try {
|
|
29437
|
+
JSON.parse(replacement);
|
|
29438
|
+
} catch (error) {
|
|
29439
|
+
add("invalid_json", error.message);
|
|
29440
|
+
}
|
|
29441
|
+
}
|
|
29442
|
+
if (/\.xml$/i.test(path3)) {
|
|
29443
|
+
const problem = xmlConcern(replacement);
|
|
29444
|
+
if (problem) add("invalid_xml", problem);
|
|
29445
|
+
}
|
|
29446
|
+
if (HTML_EXT.test(path3)) {
|
|
29447
|
+
for (const problem of jsonLdConcerns(replacement)) add("invalid_json_ld", problem);
|
|
29448
|
+
}
|
|
29449
|
+
if (original === null) return concerns;
|
|
29450
|
+
if (replacement.length < original.length * 0.6) {
|
|
29451
|
+
add("shrunk", `${Math.round(replacement.length / original.length * 100)}% of the original length`);
|
|
29452
|
+
}
|
|
29453
|
+
if (HTML_EXT.test(path3)) {
|
|
29454
|
+
for (const tag of ["</head>", "</body>", "</html>"]) {
|
|
29455
|
+
if (original.includes(tag) && !replacement.includes(tag)) add("lost_closing_tag", tag);
|
|
29456
|
+
}
|
|
29457
|
+
const lostScripts = missing(scriptSources(original), scriptSources(replacement));
|
|
29458
|
+
if (lostScripts.length) add("lost_script", lostScripts.join(", "));
|
|
29459
|
+
const lostStyles = missing(stylesheetHrefs(original), stylesheetHrefs(replacement));
|
|
29460
|
+
if (lostStyles.length) add("lost_stylesheet", lostStyles.join(", "));
|
|
29461
|
+
const lostVerification = missing(verificationTokens(original), verificationTokens(replacement));
|
|
29462
|
+
if (lostVerification.length) add("lost_verification", lostVerification.join(", "));
|
|
29463
|
+
}
|
|
29464
|
+
if (SOURCE_EXT.test(path3)) {
|
|
29465
|
+
const lostImports = missing(importSpecifiers(original), importSpecifiers(replacement));
|
|
29466
|
+
if (lostImports.length) add("lost_import", lostImports.join(", "));
|
|
29467
|
+
}
|
|
29468
|
+
if (/sitemap[^/]*\.xml$/i.test(path3)) {
|
|
29469
|
+
const before = sitemapUrlCount(original);
|
|
29470
|
+
const after = sitemapUrlCount(replacement);
|
|
29471
|
+
if (after < before) add("fewer_sitemap_urls", `${before} -> ${after}`);
|
|
29472
|
+
const newestBefore = newestLastmod(original);
|
|
29473
|
+
const newestAfter = newestLastmod(replacement);
|
|
29474
|
+
if (newestBefore !== null && newestAfter !== null && newestAfter < newestBefore) {
|
|
29475
|
+
add(
|
|
29476
|
+
"lastmod_moved_backwards",
|
|
29477
|
+
`${new Date(newestBefore).toISOString().slice(0, 10)} -> ${new Date(newestAfter).toISOString().slice(0, 10)}`
|
|
29478
|
+
);
|
|
29479
|
+
}
|
|
29480
|
+
}
|
|
29481
|
+
return concerns;
|
|
29482
|
+
}
|
|
29483
|
+
function describeConcerns(concerns) {
|
|
29484
|
+
return concerns.map((c) => `${c.code} (${c.detail})`).join("; ");
|
|
29485
|
+
}
|
|
29486
|
+
|
|
29487
|
+
// src/fixer/framework-guidance.ts
|
|
29488
|
+
var DEFAULT_MAX_CHARS = 4e3;
|
|
29489
|
+
function checkBlock(check) {
|
|
29490
|
+
const fix = check.howToFix?.trim();
|
|
29491
|
+
return [
|
|
29492
|
+
`### ${check.title}${check.code ? ` (${check.code})` : ""}`,
|
|
29493
|
+
check.description?.trim(),
|
|
29494
|
+
fix ? `How this framework wants it fixed:
|
|
29495
|
+
${fix}` : null
|
|
29496
|
+
].filter(Boolean).join("\n");
|
|
29497
|
+
}
|
|
29498
|
+
function buildFrameworkGuidance(recipe, options = {}) {
|
|
29499
|
+
if (!recipe) return "";
|
|
29500
|
+
const budget = options.maxChars ?? DEFAULT_MAX_CHARS;
|
|
29501
|
+
const reported = new Set(options.issueCodes ?? []);
|
|
29502
|
+
const header = [
|
|
29503
|
+
`## ${recipe.display_name} conventions`,
|
|
29504
|
+
`Renders on the server by default: ${recipe.ssr_default ? "yes" : "no"}.`,
|
|
29505
|
+
recipe.seo_challenges?.length ? `Known traps in this framework:
|
|
29506
|
+
${recipe.seo_challenges.map((c) => `- ${c}`).join("\n")}` : null
|
|
29507
|
+
].filter(Boolean).join("\n");
|
|
29508
|
+
const checks = recipe.checks ?? [];
|
|
29509
|
+
const relevant = checks.filter((c) => c.code && reported.has(c.code));
|
|
29510
|
+
const rest = checks.filter((c) => !relevant.includes(c));
|
|
29511
|
+
let out = header;
|
|
29512
|
+
let included = 0;
|
|
29513
|
+
for (const check of [...relevant, ...rest]) {
|
|
29514
|
+
const block = checkBlock(check);
|
|
29515
|
+
if (out.length + block.length + 2 > budget) break;
|
|
29516
|
+
out += `
|
|
29517
|
+
|
|
29518
|
+
${block}`;
|
|
29519
|
+
included++;
|
|
29520
|
+
}
|
|
29521
|
+
if (included < checks.length) {
|
|
29522
|
+
out += `
|
|
29523
|
+
|
|
29524
|
+
_(${checks.length - included} more ${recipe.display_name} checks omitted.)_`;
|
|
29525
|
+
}
|
|
29526
|
+
return out;
|
|
29527
|
+
}
|
|
29528
|
+
|
|
29484
29529
|
// src/git/commit-helper.ts
|
|
29485
29530
|
import { execSync, exec as exec2 } from "child_process";
|
|
29486
29531
|
import { promisify as promisify2 } from "util";
|
|
@@ -32001,8 +32046,12 @@ async function analyzeComprehensive(html, url, options = {}) {
|
|
|
32001
32046
|
// src/frameworks/index.ts
|
|
32002
32047
|
var frameworks_exports = {};
|
|
32003
32048
|
__export(frameworks_exports, {
|
|
32049
|
+
SCORE_FLOOR: () => SCORE_FLOOR,
|
|
32050
|
+
SIGNALS: () => SIGNALS,
|
|
32004
32051
|
SUPPORTED_FRAMEWORKS: () => SUPPORTED_FRAMEWORKS,
|
|
32052
|
+
WEIGHT: () => WEIGHT,
|
|
32005
32053
|
detectFramework: () => detectFramework,
|
|
32054
|
+
detectFromEvidence: () => detectFromEvidence,
|
|
32006
32055
|
detectFromHeaders: () => detectFromHeaders,
|
|
32007
32056
|
detectFromHtml: () => detectFromHtml,
|
|
32008
32057
|
detectFromPackageJson: () => detectFromPackageJson,
|
|
@@ -32019,19 +32068,16 @@ __export(frameworks_exports, {
|
|
|
32019
32068
|
loadRecipe: () => loadRecipe
|
|
32020
32069
|
});
|
|
32021
32070
|
var SUPPORTED_FRAMEWORKS = [
|
|
32022
|
-
"react",
|
|
32023
|
-
"nextjs",
|
|
32024
|
-
"vue",
|
|
32025
|
-
"nuxt",
|
|
32026
32071
|
"angular",
|
|
32027
|
-
"svelte",
|
|
32028
|
-
"sveltekit",
|
|
32029
32072
|
"astro",
|
|
32030
|
-
"remix",
|
|
32031
|
-
"gatsby",
|
|
32032
|
-
"rails",
|
|
32033
|
-
"laravel",
|
|
32034
32073
|
"django",
|
|
32074
|
+
"laravel",
|
|
32075
|
+
"nextjs",
|
|
32076
|
+
"nuxt",
|
|
32077
|
+
"rails",
|
|
32078
|
+
"react",
|
|
32079
|
+
"sveltekit",
|
|
32080
|
+
"vue",
|
|
32035
32081
|
"wordpress"
|
|
32036
32082
|
];
|
|
32037
32083
|
export {
|
|
@@ -32080,7 +32126,9 @@ export {
|
|
|
32080
32126
|
analyzeUrlSafety,
|
|
32081
32127
|
analyzers_exports as analyzers,
|
|
32082
32128
|
applyFixes,
|
|
32129
|
+
assessReplacement,
|
|
32083
32130
|
buildDeterministicFixes,
|
|
32131
|
+
buildFrameworkGuidance,
|
|
32084
32132
|
buildGSCApiRequest,
|
|
32085
32133
|
buildGSCRequest,
|
|
32086
32134
|
calculateAIVisibilityScore,
|
|
@@ -32121,6 +32169,7 @@ export {
|
|
|
32121
32169
|
createPullRequest,
|
|
32122
32170
|
createSEOCommit,
|
|
32123
32171
|
createSEOCommits,
|
|
32172
|
+
describeConcerns,
|
|
32124
32173
|
detectDuplicates,
|
|
32125
32174
|
detectFramework4 as detectFramework,
|
|
32126
32175
|
detectGitHubPages,
|