@wdprlib/parser 5.1.4 → 5.1.5
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.cjs +55 -27
- package/dist/index.js +55 -27
- package/package.json +1 -1
- package/src/parser/rules/block/module/listpages/parser.ts +16 -16
- package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +45 -7
- package/src/parser/rules/block/module/listpages/url-resolution/resolve.ts +3 -1
- package/src/parser/rules/block/parsing/attributes/names.ts +24 -14
package/dist/index.cjs
CHANGED
|
@@ -1298,17 +1298,22 @@ function parseInlineUntil(ctx, endType) {
|
|
|
1298
1298
|
}
|
|
1299
1299
|
// packages/parser/src/parser/rules/block/parsing/attributes/names.ts
|
|
1300
1300
|
function consumeAttributeName(ctx, startPos, startConsumed, startName, options) {
|
|
1301
|
+
if (startName === "_" && isAttributeWordToken(ctx.tokens[startPos])) {
|
|
1302
|
+
startName += ctx.tokens[startPos]?.value ?? "";
|
|
1303
|
+
startPos++;
|
|
1304
|
+
startConsumed++;
|
|
1305
|
+
}
|
|
1301
1306
|
return options.strikeHyphens ? consumeRawNameSuffix(ctx, startPos, startConsumed, startName, options.hyphenatedNames) : consumeSafeNameSuffix(ctx, startPos, startConsumed, startName);
|
|
1302
1307
|
}
|
|
1303
1308
|
function isAttributeNameToken(token5) {
|
|
1304
|
-
return token5
|
|
1309
|
+
return isAttributeWordToken(token5) || token5?.type === "UNDERSCORE";
|
|
1305
1310
|
}
|
|
1306
1311
|
function consumeSafeNameSuffix(ctx, startPos, startConsumed, startName) {
|
|
1307
1312
|
let name = startName;
|
|
1308
1313
|
let pos = startPos;
|
|
1309
1314
|
let consumed = startConsumed;
|
|
1310
|
-
while (ctx.tokens[pos]
|
|
1311
|
-
name += "
|
|
1315
|
+
while (isAttributeNameSeparator(ctx.tokens[pos]) && isAttributeWordToken(ctx.tokens[pos + 1])) {
|
|
1316
|
+
name += ctx.tokens[pos]?.value ?? "";
|
|
1312
1317
|
pos++;
|
|
1313
1318
|
consumed++;
|
|
1314
1319
|
name += ctx.tokens[pos]?.value ?? "";
|
|
@@ -1321,18 +1326,18 @@ function consumeRawNameSuffix(ctx, startPos, startConsumed, startName, hyphenate
|
|
|
1321
1326
|
let name = startName;
|
|
1322
1327
|
let pos = startPos;
|
|
1323
1328
|
let consumed = startConsumed;
|
|
1324
|
-
while (
|
|
1325
|
-
while (
|
|
1326
|
-
if (hyphenatedNames) {
|
|
1329
|
+
while (isAttributeNameSeparator(ctx.tokens[pos])) {
|
|
1330
|
+
while (isAttributeNameSeparator(ctx.tokens[pos])) {
|
|
1331
|
+
if (hyphenatedNames || ctx.tokens[pos]?.type === "UNDERSCORE") {
|
|
1327
1332
|
name += ctx.tokens[pos]?.value ?? "-";
|
|
1328
1333
|
}
|
|
1329
1334
|
pos++;
|
|
1330
1335
|
consumed++;
|
|
1331
1336
|
}
|
|
1332
|
-
if (!
|
|
1337
|
+
if (!isAttributeWordToken(ctx.tokens[pos])) {
|
|
1333
1338
|
break;
|
|
1334
1339
|
}
|
|
1335
|
-
if (hyphenatedNames) {
|
|
1340
|
+
if (hyphenatedNames || name.endsWith("_")) {
|
|
1336
1341
|
name += ctx.tokens[pos]?.value ?? "";
|
|
1337
1342
|
}
|
|
1338
1343
|
pos++;
|
|
@@ -1340,8 +1345,11 @@ function consumeRawNameSuffix(ctx, startPos, startConsumed, startName, hyphenate
|
|
|
1340
1345
|
}
|
|
1341
1346
|
return { name, pos, consumed };
|
|
1342
1347
|
}
|
|
1343
|
-
function
|
|
1344
|
-
return token5?.type === "TEXT"
|
|
1348
|
+
function isAttributeWordToken(token5) {
|
|
1349
|
+
return token5?.type === "TEXT" || token5?.type === "IDENTIFIER";
|
|
1350
|
+
}
|
|
1351
|
+
function isAttributeNameSeparator(token5) {
|
|
1352
|
+
return token5?.type === "TEXT" && token5.value === "-" || token5?.type === "STRIKE_MARKER" || token5?.type === "UNDERSCORE";
|
|
1345
1353
|
}
|
|
1346
1354
|
|
|
1347
1355
|
// packages/parser/src/parser/rules/block/parsing/attributes/values.ts
|
|
@@ -4456,18 +4464,18 @@ var listPagesModuleRule = {
|
|
|
4456
4464
|
wrapper,
|
|
4457
4465
|
rss
|
|
4458
4466
|
} = args;
|
|
4459
|
-
const linkTo = args["link-to"] ?? args.linkto;
|
|
4460
|
-
const createdBy = args["created-by"] ?? args.createdby;
|
|
4461
|
-
const createdAt = args["created-at"] ?? args.createdat;
|
|
4462
|
-
const updatedAt = args["updated-at"] ?? args.updatedat;
|
|
4463
|
-
const perPage = args["per-page"] ?? args.perpage;
|
|
4464
|
-
const prependLine = args["prepend-line"] ?? args.prependline;
|
|
4465
|
-
const appendLine = args["append-line"] ?? args.appendline;
|
|
4466
|
-
const rssDescription = args["rss-description"] ?? args.rssdescription;
|
|
4467
|
-
const rssHome = args["rss-home"] ?? args.rsshome;
|
|
4468
|
-
const rssLimit = args["rss-limit"] ?? args.rsslimit;
|
|
4469
|
-
const rssOnly = args["rss-only"] ?? args.rssonly;
|
|
4470
|
-
const urlAttrPrefix = args["url-attr-prefix"] ?? args.urlattrprefix;
|
|
4467
|
+
const linkTo = args["link-to"] ?? args.linkto ?? args.link_to;
|
|
4468
|
+
const createdBy = args["created-by"] ?? args.createdby ?? args.created_by;
|
|
4469
|
+
const createdAt = args["created-at"] ?? args.createdat ?? args.created_at;
|
|
4470
|
+
const updatedAt = args["updated-at"] ?? args.updatedat ?? args.updated_at;
|
|
4471
|
+
const perPage = args["per-page"] ?? args.perpage ?? args.per_page;
|
|
4472
|
+
const prependLine = args["prepend-line"] ?? args.prependline ?? args.prepend_line;
|
|
4473
|
+
const appendLine = args["append-line"] ?? args.appendline ?? args.append_line;
|
|
4474
|
+
const rssDescription = args["rss-description"] ?? args.rssdescription ?? args.rss_description;
|
|
4475
|
+
const rssHome = args["rss-home"] ?? args.rsshome ?? args.rss_home;
|
|
4476
|
+
const rssLimit = args["rss-limit"] ?? args.rsslimit ?? args.rss_limit;
|
|
4477
|
+
const rssOnly = args["rss-only"] ?? args.rssonly ?? args.rss_only;
|
|
4478
|
+
const urlAttrPrefix = args["url-attr-prefix"] ?? args.urlattrprefix ?? args.url_attr_prefix;
|
|
4471
4479
|
const rawArgs = { ...args };
|
|
4472
4480
|
return {
|
|
4473
4481
|
module: "list-pages",
|
|
@@ -5979,7 +5987,12 @@ function setsEqual(left, right) {
|
|
|
5979
5987
|
var URL_RESOLVABLE_FIELDS = [
|
|
5980
5988
|
{ attr: "offset", queryKey: "offset", type: "number" },
|
|
5981
5989
|
{ attr: "limit", queryKey: "limit", type: "number" },
|
|
5982
|
-
{
|
|
5990
|
+
{
|
|
5991
|
+
attr: "per-page",
|
|
5992
|
+
queryKey: "perPage",
|
|
5993
|
+
type: "number",
|
|
5994
|
+
aliases: ["perpage", "per_page"]
|
|
5995
|
+
},
|
|
5983
5996
|
{ attr: "order", queryKey: "order", type: "string" },
|
|
5984
5997
|
{ attr: "tags", queryKey: "tags", type: "string", urlAttrs: ["tag"] },
|
|
5985
5998
|
{ attr: "category", queryKey: "category", type: "string" },
|
|
@@ -5987,9 +6000,24 @@ var URL_RESOLVABLE_FIELDS = [
|
|
|
5987
6000
|
{ attr: "range", queryKey: "range", type: "string" },
|
|
5988
6001
|
{ attr: "name", queryKey: "name", type: "string" },
|
|
5989
6002
|
{ attr: "fullname", queryKey: "fullname", type: "string" },
|
|
5990
|
-
{
|
|
5991
|
-
|
|
5992
|
-
|
|
6003
|
+
{
|
|
6004
|
+
attr: "created-at",
|
|
6005
|
+
queryKey: "createdAt",
|
|
6006
|
+
type: "string",
|
|
6007
|
+
aliases: ["createdat", "created_at"]
|
|
6008
|
+
},
|
|
6009
|
+
{
|
|
6010
|
+
attr: "updated-at",
|
|
6011
|
+
queryKey: "updatedAt",
|
|
6012
|
+
type: "string",
|
|
6013
|
+
aliases: ["updatedat", "updated_at"]
|
|
6014
|
+
},
|
|
6015
|
+
{
|
|
6016
|
+
attr: "created-by",
|
|
6017
|
+
queryKey: "createdBy",
|
|
6018
|
+
type: "string",
|
|
6019
|
+
aliases: ["createdby", "created_by"]
|
|
6020
|
+
},
|
|
5993
6021
|
{ attr: "rating", queryKey: "rating", type: "string" },
|
|
5994
6022
|
{ attr: "votes", queryKey: "votes", type: "string" },
|
|
5995
6023
|
{ attr: "reverse", queryKey: "reverse", type: "boolean" }
|
|
@@ -6312,7 +6340,7 @@ function resolveQuery(requirement, urlParams) {
|
|
|
6312
6340
|
const { query, rawAttributes, urlAttrPrefix } = requirement;
|
|
6313
6341
|
const resolved = { ...query };
|
|
6314
6342
|
for (const field of URL_RESOLVABLE_FIELDS) {
|
|
6315
|
-
const rawValue =
|
|
6343
|
+
const rawValue = [field.attr, ...field.aliases ?? []].map((attr) => rawAttributes[attr]).find((value) => value !== undefined);
|
|
6316
6344
|
if (!rawValue)
|
|
6317
6345
|
continue;
|
|
6318
6346
|
const resolvedValue = resolveUrlValue(rawValue, getUrlParamNames(field), urlParams, urlAttrPrefix);
|
package/dist/index.js
CHANGED
|
@@ -1233,17 +1233,22 @@ function parseInlineUntil(ctx, endType) {
|
|
|
1233
1233
|
}
|
|
1234
1234
|
// packages/parser/src/parser/rules/block/parsing/attributes/names.ts
|
|
1235
1235
|
function consumeAttributeName(ctx, startPos, startConsumed, startName, options) {
|
|
1236
|
+
if (startName === "_" && isAttributeWordToken(ctx.tokens[startPos])) {
|
|
1237
|
+
startName += ctx.tokens[startPos]?.value ?? "";
|
|
1238
|
+
startPos++;
|
|
1239
|
+
startConsumed++;
|
|
1240
|
+
}
|
|
1236
1241
|
return options.strikeHyphens ? consumeRawNameSuffix(ctx, startPos, startConsumed, startName, options.hyphenatedNames) : consumeSafeNameSuffix(ctx, startPos, startConsumed, startName);
|
|
1237
1242
|
}
|
|
1238
1243
|
function isAttributeNameToken(token5) {
|
|
1239
|
-
return token5
|
|
1244
|
+
return isAttributeWordToken(token5) || token5?.type === "UNDERSCORE";
|
|
1240
1245
|
}
|
|
1241
1246
|
function consumeSafeNameSuffix(ctx, startPos, startConsumed, startName) {
|
|
1242
1247
|
let name = startName;
|
|
1243
1248
|
let pos = startPos;
|
|
1244
1249
|
let consumed = startConsumed;
|
|
1245
|
-
while (ctx.tokens[pos]
|
|
1246
|
-
name += "
|
|
1250
|
+
while (isAttributeNameSeparator(ctx.tokens[pos]) && isAttributeWordToken(ctx.tokens[pos + 1])) {
|
|
1251
|
+
name += ctx.tokens[pos]?.value ?? "";
|
|
1247
1252
|
pos++;
|
|
1248
1253
|
consumed++;
|
|
1249
1254
|
name += ctx.tokens[pos]?.value ?? "";
|
|
@@ -1256,18 +1261,18 @@ function consumeRawNameSuffix(ctx, startPos, startConsumed, startName, hyphenate
|
|
|
1256
1261
|
let name = startName;
|
|
1257
1262
|
let pos = startPos;
|
|
1258
1263
|
let consumed = startConsumed;
|
|
1259
|
-
while (
|
|
1260
|
-
while (
|
|
1261
|
-
if (hyphenatedNames) {
|
|
1264
|
+
while (isAttributeNameSeparator(ctx.tokens[pos])) {
|
|
1265
|
+
while (isAttributeNameSeparator(ctx.tokens[pos])) {
|
|
1266
|
+
if (hyphenatedNames || ctx.tokens[pos]?.type === "UNDERSCORE") {
|
|
1262
1267
|
name += ctx.tokens[pos]?.value ?? "-";
|
|
1263
1268
|
}
|
|
1264
1269
|
pos++;
|
|
1265
1270
|
consumed++;
|
|
1266
1271
|
}
|
|
1267
|
-
if (!
|
|
1272
|
+
if (!isAttributeWordToken(ctx.tokens[pos])) {
|
|
1268
1273
|
break;
|
|
1269
1274
|
}
|
|
1270
|
-
if (hyphenatedNames) {
|
|
1275
|
+
if (hyphenatedNames || name.endsWith("_")) {
|
|
1271
1276
|
name += ctx.tokens[pos]?.value ?? "";
|
|
1272
1277
|
}
|
|
1273
1278
|
pos++;
|
|
@@ -1275,8 +1280,11 @@ function consumeRawNameSuffix(ctx, startPos, startConsumed, startName, hyphenate
|
|
|
1275
1280
|
}
|
|
1276
1281
|
return { name, pos, consumed };
|
|
1277
1282
|
}
|
|
1278
|
-
function
|
|
1279
|
-
return token5?.type === "TEXT"
|
|
1283
|
+
function isAttributeWordToken(token5) {
|
|
1284
|
+
return token5?.type === "TEXT" || token5?.type === "IDENTIFIER";
|
|
1285
|
+
}
|
|
1286
|
+
function isAttributeNameSeparator(token5) {
|
|
1287
|
+
return token5?.type === "TEXT" && token5.value === "-" || token5?.type === "STRIKE_MARKER" || token5?.type === "UNDERSCORE";
|
|
1280
1288
|
}
|
|
1281
1289
|
|
|
1282
1290
|
// packages/parser/src/parser/rules/block/parsing/attributes/values.ts
|
|
@@ -4391,18 +4399,18 @@ var listPagesModuleRule = {
|
|
|
4391
4399
|
wrapper,
|
|
4392
4400
|
rss
|
|
4393
4401
|
} = args;
|
|
4394
|
-
const linkTo = args["link-to"] ?? args.linkto;
|
|
4395
|
-
const createdBy = args["created-by"] ?? args.createdby;
|
|
4396
|
-
const createdAt = args["created-at"] ?? args.createdat;
|
|
4397
|
-
const updatedAt = args["updated-at"] ?? args.updatedat;
|
|
4398
|
-
const perPage = args["per-page"] ?? args.perpage;
|
|
4399
|
-
const prependLine = args["prepend-line"] ?? args.prependline;
|
|
4400
|
-
const appendLine = args["append-line"] ?? args.appendline;
|
|
4401
|
-
const rssDescription = args["rss-description"] ?? args.rssdescription;
|
|
4402
|
-
const rssHome = args["rss-home"] ?? args.rsshome;
|
|
4403
|
-
const rssLimit = args["rss-limit"] ?? args.rsslimit;
|
|
4404
|
-
const rssOnly = args["rss-only"] ?? args.rssonly;
|
|
4405
|
-
const urlAttrPrefix = args["url-attr-prefix"] ?? args.urlattrprefix;
|
|
4402
|
+
const linkTo = args["link-to"] ?? args.linkto ?? args.link_to;
|
|
4403
|
+
const createdBy = args["created-by"] ?? args.createdby ?? args.created_by;
|
|
4404
|
+
const createdAt = args["created-at"] ?? args.createdat ?? args.created_at;
|
|
4405
|
+
const updatedAt = args["updated-at"] ?? args.updatedat ?? args.updated_at;
|
|
4406
|
+
const perPage = args["per-page"] ?? args.perpage ?? args.per_page;
|
|
4407
|
+
const prependLine = args["prepend-line"] ?? args.prependline ?? args.prepend_line;
|
|
4408
|
+
const appendLine = args["append-line"] ?? args.appendline ?? args.append_line;
|
|
4409
|
+
const rssDescription = args["rss-description"] ?? args.rssdescription ?? args.rss_description;
|
|
4410
|
+
const rssHome = args["rss-home"] ?? args.rsshome ?? args.rss_home;
|
|
4411
|
+
const rssLimit = args["rss-limit"] ?? args.rsslimit ?? args.rss_limit;
|
|
4412
|
+
const rssOnly = args["rss-only"] ?? args.rssonly ?? args.rss_only;
|
|
4413
|
+
const urlAttrPrefix = args["url-attr-prefix"] ?? args.urlattrprefix ?? args.url_attr_prefix;
|
|
4406
4414
|
const rawArgs = { ...args };
|
|
4407
4415
|
return {
|
|
4408
4416
|
module: "list-pages",
|
|
@@ -5914,7 +5922,12 @@ function setsEqual(left, right) {
|
|
|
5914
5922
|
var URL_RESOLVABLE_FIELDS = [
|
|
5915
5923
|
{ attr: "offset", queryKey: "offset", type: "number" },
|
|
5916
5924
|
{ attr: "limit", queryKey: "limit", type: "number" },
|
|
5917
|
-
{
|
|
5925
|
+
{
|
|
5926
|
+
attr: "per-page",
|
|
5927
|
+
queryKey: "perPage",
|
|
5928
|
+
type: "number",
|
|
5929
|
+
aliases: ["perpage", "per_page"]
|
|
5930
|
+
},
|
|
5918
5931
|
{ attr: "order", queryKey: "order", type: "string" },
|
|
5919
5932
|
{ attr: "tags", queryKey: "tags", type: "string", urlAttrs: ["tag"] },
|
|
5920
5933
|
{ attr: "category", queryKey: "category", type: "string" },
|
|
@@ -5922,9 +5935,24 @@ var URL_RESOLVABLE_FIELDS = [
|
|
|
5922
5935
|
{ attr: "range", queryKey: "range", type: "string" },
|
|
5923
5936
|
{ attr: "name", queryKey: "name", type: "string" },
|
|
5924
5937
|
{ attr: "fullname", queryKey: "fullname", type: "string" },
|
|
5925
|
-
{
|
|
5926
|
-
|
|
5927
|
-
|
|
5938
|
+
{
|
|
5939
|
+
attr: "created-at",
|
|
5940
|
+
queryKey: "createdAt",
|
|
5941
|
+
type: "string",
|
|
5942
|
+
aliases: ["createdat", "created_at"]
|
|
5943
|
+
},
|
|
5944
|
+
{
|
|
5945
|
+
attr: "updated-at",
|
|
5946
|
+
queryKey: "updatedAt",
|
|
5947
|
+
type: "string",
|
|
5948
|
+
aliases: ["updatedat", "updated_at"]
|
|
5949
|
+
},
|
|
5950
|
+
{
|
|
5951
|
+
attr: "created-by",
|
|
5952
|
+
queryKey: "createdBy",
|
|
5953
|
+
type: "string",
|
|
5954
|
+
aliases: ["createdby", "created_by"]
|
|
5955
|
+
},
|
|
5928
5956
|
{ attr: "rating", queryKey: "rating", type: "string" },
|
|
5929
5957
|
{ attr: "votes", queryKey: "votes", type: "string" },
|
|
5930
5958
|
{ attr: "reverse", queryKey: "reverse", type: "boolean" }
|
|
@@ -6247,7 +6275,7 @@ function resolveQuery(requirement, urlParams) {
|
|
|
6247
6275
|
const { query, rawAttributes, urlAttrPrefix } = requirement;
|
|
6248
6276
|
const resolved = { ...query };
|
|
6249
6277
|
for (const field of URL_RESOLVABLE_FIELDS) {
|
|
6250
|
-
const rawValue =
|
|
6278
|
+
const rawValue = [field.attr, ...field.aliases ?? []].map((attr) => rawAttributes[attr]).find((value) => value !== undefined);
|
|
6251
6279
|
if (!rawValue)
|
|
6252
6280
|
continue;
|
|
6253
6281
|
const resolvedValue = resolveUrlValue(rawValue, getUrlParamNames(field), urlParams, urlAttrPrefix);
|
package/package.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Parser rule for the Wikidot `[[module ListPages ...]]` block.
|
|
4
4
|
*
|
|
5
5
|
* Parses the module's attributes into a structured `list-pages` Module AST node.
|
|
6
|
-
* Handles
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Handles hyphenated (`link-to`), concatenated (`linkto`), and snake_case (`link_to`)
|
|
7
|
+
* attribute name formats. The raw attribute values are preserved in the `attributes`
|
|
8
|
+
* field for `@URL` resolution by external applications.
|
|
9
9
|
*
|
|
10
10
|
* @module
|
|
11
11
|
*/
|
|
@@ -51,19 +51,19 @@ export const listPagesModuleRule: ModuleRule = {
|
|
|
51
51
|
wrapper,
|
|
52
52
|
rss,
|
|
53
53
|
} = args;
|
|
54
|
-
//
|
|
55
|
-
const linkTo = args["link-to"] ?? args.linkto;
|
|
56
|
-
const createdBy = args["created-by"] ?? args.createdby;
|
|
57
|
-
const createdAt = args["created-at"] ?? args.createdat;
|
|
58
|
-
const updatedAt = args["updated-at"] ?? args.updatedat;
|
|
59
|
-
const perPage = args["per-page"] ?? args.perpage;
|
|
60
|
-
const prependLine = args["prepend-line"] ?? args.prependline;
|
|
61
|
-
const appendLine = args["append-line"] ?? args.appendline;
|
|
62
|
-
const rssDescription = args["rss-description"] ?? args.rssdescription;
|
|
63
|
-
const rssHome = args["rss-home"] ?? args.rsshome;
|
|
64
|
-
const rssLimit = args["rss-limit"] ?? args.rsslimit;
|
|
65
|
-
const rssOnly = args["rss-only"] ?? args.rssonly;
|
|
66
|
-
const urlAttrPrefix = args["url-attr-prefix"] ?? args.urlattrprefix;
|
|
54
|
+
// Compound attributes accept Wikidot's supported spelling variants.
|
|
55
|
+
const linkTo = args["link-to"] ?? args.linkto ?? args.link_to;
|
|
56
|
+
const createdBy = args["created-by"] ?? args.createdby ?? args.created_by;
|
|
57
|
+
const createdAt = args["created-at"] ?? args.createdat ?? args.created_at;
|
|
58
|
+
const updatedAt = args["updated-at"] ?? args.updatedat ?? args.updated_at;
|
|
59
|
+
const perPage = args["per-page"] ?? args.perpage ?? args.per_page;
|
|
60
|
+
const prependLine = args["prepend-line"] ?? args.prependline ?? args.prepend_line;
|
|
61
|
+
const appendLine = args["append-line"] ?? args.appendline ?? args.append_line;
|
|
62
|
+
const rssDescription = args["rss-description"] ?? args.rssdescription ?? args.rss_description;
|
|
63
|
+
const rssHome = args["rss-home"] ?? args.rsshome ?? args.rss_home;
|
|
64
|
+
const rssLimit = args["rss-limit"] ?? args.rsslimit ?? args.rss_limit;
|
|
65
|
+
const rssOnly = args["rss-only"] ?? args.rssonly ?? args.rss_only;
|
|
66
|
+
const urlAttrPrefix = args["url-attr-prefix"] ?? args.urlattrprefix ?? args.url_attr_prefix;
|
|
67
67
|
|
|
68
68
|
// Store all raw arguments for @URL resolution by external apps
|
|
69
69
|
const rawArgs: Record<string, string> = { ...args };
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import type { ListPagesQuery } from "../types";
|
|
2
2
|
|
|
3
3
|
export type UrlResolvableField =
|
|
4
|
-
| {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
| {
|
|
5
|
+
attr: string;
|
|
6
|
+
queryKey: StringUrlQueryKey;
|
|
7
|
+
type: "string";
|
|
8
|
+
aliases?: readonly string[];
|
|
9
|
+
urlAttrs?: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
| {
|
|
12
|
+
attr: string;
|
|
13
|
+
queryKey: NumberUrlQueryKey;
|
|
14
|
+
type: "number";
|
|
15
|
+
aliases?: readonly string[];
|
|
16
|
+
urlAttrs?: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
| {
|
|
19
|
+
attr: string;
|
|
20
|
+
queryKey: BooleanUrlQueryKey;
|
|
21
|
+
type: "boolean";
|
|
22
|
+
aliases?: readonly string[];
|
|
23
|
+
urlAttrs?: readonly string[];
|
|
24
|
+
};
|
|
7
25
|
|
|
8
26
|
type StringUrlQueryKey = Extract<
|
|
9
27
|
keyof ListPagesQuery,
|
|
@@ -31,7 +49,12 @@ type BooleanUrlQueryKey = Extract<keyof ListPagesQuery, "reverse">;
|
|
|
31
49
|
export const URL_RESOLVABLE_FIELDS: readonly UrlResolvableField[] = [
|
|
32
50
|
{ attr: "offset", queryKey: "offset", type: "number" },
|
|
33
51
|
{ attr: "limit", queryKey: "limit", type: "number" },
|
|
34
|
-
{
|
|
52
|
+
{
|
|
53
|
+
attr: "per-page",
|
|
54
|
+
queryKey: "perPage",
|
|
55
|
+
type: "number",
|
|
56
|
+
aliases: ["perpage", "per_page"],
|
|
57
|
+
},
|
|
35
58
|
{ attr: "order", queryKey: "order", type: "string" },
|
|
36
59
|
{ attr: "tags", queryKey: "tags", type: "string", urlAttrs: ["tag"] },
|
|
37
60
|
{ attr: "category", queryKey: "category", type: "string" },
|
|
@@ -39,9 +62,24 @@ export const URL_RESOLVABLE_FIELDS: readonly UrlResolvableField[] = [
|
|
|
39
62
|
{ attr: "range", queryKey: "range", type: "string" },
|
|
40
63
|
{ attr: "name", queryKey: "name", type: "string" },
|
|
41
64
|
{ attr: "fullname", queryKey: "fullname", type: "string" },
|
|
42
|
-
{
|
|
43
|
-
|
|
44
|
-
|
|
65
|
+
{
|
|
66
|
+
attr: "created-at",
|
|
67
|
+
queryKey: "createdAt",
|
|
68
|
+
type: "string",
|
|
69
|
+
aliases: ["createdat", "created_at"],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
attr: "updated-at",
|
|
73
|
+
queryKey: "updatedAt",
|
|
74
|
+
type: "string",
|
|
75
|
+
aliases: ["updatedat", "updated_at"],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
attr: "created-by",
|
|
79
|
+
queryKey: "createdBy",
|
|
80
|
+
type: "string",
|
|
81
|
+
aliases: ["createdby", "created_by"],
|
|
82
|
+
},
|
|
45
83
|
{ attr: "rating", queryKey: "rating", type: "string" },
|
|
46
84
|
{ attr: "votes", queryKey: "votes", type: "string" },
|
|
47
85
|
{ attr: "reverse", queryKey: "reverse", type: "boolean" },
|
|
@@ -22,7 +22,9 @@ export function resolveQuery(
|
|
|
22
22
|
const resolved: ListPagesQuery = { ...query };
|
|
23
23
|
|
|
24
24
|
for (const field of URL_RESOLVABLE_FIELDS) {
|
|
25
|
-
const rawValue =
|
|
25
|
+
const rawValue = [field.attr, ...(field.aliases ?? [])]
|
|
26
|
+
.map((attr) => rawAttributes[attr])
|
|
27
|
+
.find((value) => value !== undefined);
|
|
26
28
|
if (!rawValue) continue;
|
|
27
29
|
|
|
28
30
|
const resolvedValue = resolveUrlValue(
|
|
@@ -19,13 +19,19 @@ export function consumeAttributeName(
|
|
|
19
19
|
startName: string,
|
|
20
20
|
options: AttributeNameOptions,
|
|
21
21
|
): AttributeNameResult {
|
|
22
|
+
if (startName === "_" && isAttributeWordToken(ctx.tokens[startPos])) {
|
|
23
|
+
startName += ctx.tokens[startPos]?.value ?? "";
|
|
24
|
+
startPos++;
|
|
25
|
+
startConsumed++;
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
return options.strikeHyphens
|
|
23
29
|
? consumeRawNameSuffix(ctx, startPos, startConsumed, startName, options.hyphenatedNames)
|
|
24
30
|
: consumeSafeNameSuffix(ctx, startPos, startConsumed, startName);
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
export function isAttributeNameToken(token: Token | undefined): token is Token {
|
|
28
|
-
return token
|
|
34
|
+
return isAttributeWordToken(token) || token?.type === "UNDERSCORE";
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
function consumeSafeNameSuffix(
|
|
@@ -38,12 +44,8 @@ function consumeSafeNameSuffix(
|
|
|
38
44
|
let pos = startPos;
|
|
39
45
|
let consumed = startConsumed;
|
|
40
46
|
|
|
41
|
-
while (
|
|
42
|
-
ctx.tokens[pos]?.
|
|
43
|
-
ctx.tokens[pos]?.value === "-" &&
|
|
44
|
-
isAttributeNameToken(ctx.tokens[pos + 1])
|
|
45
|
-
) {
|
|
46
|
-
name += "-";
|
|
47
|
+
while (isAttributeNameSeparator(ctx.tokens[pos]) && isAttributeWordToken(ctx.tokens[pos + 1])) {
|
|
48
|
+
name += ctx.tokens[pos]?.value ?? "";
|
|
47
49
|
pos++;
|
|
48
50
|
consumed++;
|
|
49
51
|
name += ctx.tokens[pos]?.value ?? "";
|
|
@@ -65,20 +67,20 @@ function consumeRawNameSuffix(
|
|
|
65
67
|
let pos = startPos;
|
|
66
68
|
let consumed = startConsumed;
|
|
67
69
|
|
|
68
|
-
while (
|
|
69
|
-
while (
|
|
70
|
-
if (hyphenatedNames) {
|
|
70
|
+
while (isAttributeNameSeparator(ctx.tokens[pos])) {
|
|
71
|
+
while (isAttributeNameSeparator(ctx.tokens[pos])) {
|
|
72
|
+
if (hyphenatedNames || ctx.tokens[pos]?.type === "UNDERSCORE") {
|
|
71
73
|
name += ctx.tokens[pos]?.value ?? "-";
|
|
72
74
|
}
|
|
73
75
|
pos++;
|
|
74
76
|
consumed++;
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
if (!
|
|
79
|
+
if (!isAttributeWordToken(ctx.tokens[pos])) {
|
|
78
80
|
break;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
if (hyphenatedNames) {
|
|
83
|
+
if (hyphenatedNames || name.endsWith("_")) {
|
|
82
84
|
name += ctx.tokens[pos]?.value ?? "";
|
|
83
85
|
}
|
|
84
86
|
pos++;
|
|
@@ -88,6 +90,14 @@ function consumeRawNameSuffix(
|
|
|
88
90
|
return { name, pos, consumed };
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
function
|
|
92
|
-
return
|
|
93
|
+
function isAttributeWordToken(token: Token | undefined): boolean {
|
|
94
|
+
return token?.type === "TEXT" || token?.type === "IDENTIFIER";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isAttributeNameSeparator(token: Token | undefined): boolean {
|
|
98
|
+
return (
|
|
99
|
+
(token?.type === "TEXT" && token.value === "-") ||
|
|
100
|
+
token?.type === "STRIKE_MARKER" ||
|
|
101
|
+
token?.type === "UNDERSCORE"
|
|
102
|
+
);
|
|
93
103
|
}
|