@taskless-app/shared 0.1.41 → 0.1.42
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/brokenUrl.d.ts +8 -0
- package/dist/brokenUrl.js +111 -0
- package/dist/brokenUrl.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Адрес в конце строки — любой (для починки href уже собранной ссылки). */
|
|
2
|
+
export declare function isUrlTail(text: string): boolean;
|
|
3
|
+
/** Адрес в конце строки, который выглядит ОБОРВАННЫМ, а не просто законченным. */
|
|
4
|
+
export declare function isBrokenUrlTail(text: string): boolean;
|
|
5
|
+
/** Строка целиком — хвост оборванного адреса, а не новая мысль. */
|
|
6
|
+
export declare function isUrlContinuation(text: string): boolean;
|
|
7
|
+
/** Плоский текст: строки-хвосты приклеиваются к предыдущей строке без пробела. */
|
|
8
|
+
export declare function joinBrokenUrlLines(text: string): string;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Склейка адреса, разорванного переносами строк.
|
|
2
|
+
//
|
|
3
|
+
// PRJ-122: длинный адрес, скопированный из PDF/письма/мессенджера, приезжает
|
|
4
|
+
// разбитым переносами по `&`, и разбор «строка = абзац» линкует только первую
|
|
5
|
+
// строку — хвост параметров остаётся обычным текстом.
|
|
6
|
+
//
|
|
7
|
+
// MOVE-68: то же самое приезжает и ИЗ ИМПОРТА — так адрес лежал в markdown
|
|
8
|
+
// YouTrack. Поэтому чистая текстовая часть склейки живёт здесь, в shared: DOM
|
|
9
|
+
// ей не нужен, а потребителей у неё двое — редактор (путь вставки,
|
|
10
|
+
// `packages/editor/src/markdownPaste.ts`, по всему тексту буфера) и коннекторы
|
|
11
|
+
// импорта (`youtrack/body.ts`, поабзацно: пока строки абзаца ещё строки, а не
|
|
12
|
+
// hardBreak'ы, из которых линкуется только первая).
|
|
13
|
+
//
|
|
14
|
+
// Условие склейки нарочно узкое, чтобы не портить обычный многострочный текст:
|
|
15
|
+
// 1) предыдущая строка кончается ОБОРВАННЫМ адресом: в нём уже начался query
|
|
16
|
+
// (`?…`) либо он обрывается на разделителе (`?`, `&`, `=`, `/`);
|
|
17
|
+
// 2) следующая целиком — хвост этого адреса: либо параметр query
|
|
18
|
+
// (`&key=value`, `?key=value`), либо продолжение пути/фрагмента
|
|
19
|
+
// (`/…`, `#…`, `=…`) — и в любом случае БЕЗ пробелов внутри.
|
|
20
|
+
// Требование (2) отсекает «Документация: https://x\n/api/tasks — список задач»:
|
|
21
|
+
// строка с пробелами хвостом адреса не считается.
|
|
22
|
+
// Требование (1) — правка по ревью PR #1130: «просто адрес» признаком обрыва не
|
|
23
|
+
// считается, иначе частый паттерн
|
|
24
|
+
// Fixed in https://github.com/org/repo/commit/abcd123
|
|
25
|
+
// #456
|
|
26
|
+
// молча склеивался бы в один абзац, приклеивая ссылку на задачу к URL как
|
|
27
|
+
// fragment. По той же причине голый `#123` (номер задачи/issue) хвостом не
|
|
28
|
+
// считается никогда — даже после оборванного query.
|
|
29
|
+
const RE_URL_TAIL = /https?:\/\/\S*$/i;
|
|
30
|
+
const RE_URL_BROKEN_TAIL = /https?:\/\/\S*(?:\?\S*|[?&=/])$/i;
|
|
31
|
+
const RE_CONT_QUERY = /^[&?][^\s&?#=]+=\S*$/;
|
|
32
|
+
const RE_CONT_PATH = /^[/#=]\S*$/;
|
|
33
|
+
const RE_ISSUE_REF = /^#\d+$/;
|
|
34
|
+
// Огороженный код: внутри забора перевод строки ЗНАЧИМ, склейка там ломает
|
|
35
|
+
// содержимое. `PUBLIC_URL=https://app.example.com/` + `#PUBLIC_URL=…` — две
|
|
36
|
+
// строки .env, а не разорванный адрес. DOM-близнец этой склейки код пропускает
|
|
37
|
+
// давно (`joinBrokenUrlHtml` → `significantTexts`: `closest("pre, code")`),
|
|
38
|
+
// текстовая версия должна вести себя так же.
|
|
39
|
+
//
|
|
40
|
+
// Грамматика забора — CommonMark, ровно как у `marked`, которым разбирает
|
|
41
|
+
// вставку редактор (единственный, кто зовёт склейку по ЦЕЛОМУ тексту; импорт
|
|
42
|
+
// YouTrack зовёт её поабзацно, когда заборы уже разобраны). Отсюда две
|
|
43
|
+
// строгости, без которых состояние забора расходится с парсером и склейка либо
|
|
44
|
+
// молча выключается до конца текста, либо, наоборот, лезет в код:
|
|
45
|
+
// • открывающий забор может нести info string (```` ```js ````, ```` ``` смотри лог ````),
|
|
46
|
+
// закрывающий — нет: он ГОЛЫЙ;
|
|
47
|
+
// • закрывать умеет только тот же символ и не короче открывшего: `~~~`
|
|
48
|
+
// внутри ```` ``` ````-блока — просто строка кода.
|
|
49
|
+
// Ревью PR #1135: широкий `/^\s*(```|~~~)/` на обе роли путал и то и другое.
|
|
50
|
+
const RE_FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
|
|
51
|
+
/** Забор закрыт: тот же символ, не короче открывшего, и после него пусто. */
|
|
52
|
+
function closesFence(line, marker) {
|
|
53
|
+
const m = RE_FENCE_OPEN.exec(line);
|
|
54
|
+
return m !== null && m[1][0] === marker[0] && m[1].length >= marker.length && m[2].trim() === "";
|
|
55
|
+
}
|
|
56
|
+
/** Адрес в конце строки — любой (для починки href уже собранной ссылки). */
|
|
57
|
+
export function isUrlTail(text) {
|
|
58
|
+
return RE_URL_TAIL.test(text.replace(/\s+$/, ""));
|
|
59
|
+
}
|
|
60
|
+
/** Адрес в конце строки, который выглядит ОБОРВАННЫМ, а не просто законченным. */
|
|
61
|
+
export function isBrokenUrlTail(text) {
|
|
62
|
+
return RE_URL_BROKEN_TAIL.test(text.replace(/\s+$/, ""));
|
|
63
|
+
}
|
|
64
|
+
/** Строка целиком — хвост оборванного адреса, а не новая мысль. */
|
|
65
|
+
export function isUrlContinuation(text) {
|
|
66
|
+
const t = text.trim();
|
|
67
|
+
if (t.length < 2 || RE_ISSUE_REF.test(t))
|
|
68
|
+
return false;
|
|
69
|
+
return RE_CONT_QUERY.test(t) || RE_CONT_PATH.test(t);
|
|
70
|
+
}
|
|
71
|
+
/** Плоский текст: строки-хвосты приклеиваются к предыдущей строке без пробела. */
|
|
72
|
+
export function joinBrokenUrlLines(text) {
|
|
73
|
+
if (!text || !/[\r\n]/.test(text))
|
|
74
|
+
return text;
|
|
75
|
+
const out = [];
|
|
76
|
+
let joined = false;
|
|
77
|
+
// Маркер открытого забора (``` / ~~~~ и т.п.) либо null — забор закрыт.
|
|
78
|
+
// Непарный забор оставляет режим включённым до конца текста, то есть склейки
|
|
79
|
+
// не будет: отказаться от склейки безопаснее, чем испортить код. Так же
|
|
80
|
+
// читает незакрытый забор и сам CommonMark — до конца документа.
|
|
81
|
+
let fence = null;
|
|
82
|
+
for (const line of text.split(/\r\n?|\n/)) {
|
|
83
|
+
if (fence !== null) {
|
|
84
|
+
if (closesFence(line, fence))
|
|
85
|
+
fence = null;
|
|
86
|
+
out.push(line);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const open = RE_FENCE_OPEN.exec(line);
|
|
90
|
+
// Бэктик-забор с бэктиком в info string CommonMark забором не считает
|
|
91
|
+
// (иначе инлайн-код спутался бы с блочным) — и мы тоже.
|
|
92
|
+
if (open && !(open[1][0] === "`" && open[2].includes("`"))) {
|
|
93
|
+
fence = open[1];
|
|
94
|
+
out.push(line);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const prev = out.length > 0 ? out[out.length - 1] : undefined;
|
|
98
|
+
if (prev !== undefined && isBrokenUrlTail(prev) && isUrlContinuation(line)) {
|
|
99
|
+
out[out.length - 1] = prev.replace(/\s+$/, "") + line.trim();
|
|
100
|
+
joined = true;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
out.push(line);
|
|
104
|
+
}
|
|
105
|
+
// Ничего не склеили — отдаём ИСХОДНУЮ строку, а не пересобранную. Иначе
|
|
106
|
+
// CRLF (буфер Windows) схлопнулся бы в \n, сравнение `text === raw` в
|
|
107
|
+
// clipboardTextParser редактора стало бы ложным, и любая обычная многострочная
|
|
108
|
+
// вставка пошла бы мимо дефолтного разбора ProseMirror — теряя марки каретки.
|
|
109
|
+
return joined ? out.join("\n") : text;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=brokenUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brokenUrl.js","sourceRoot":"","sources":["../src/brokenUrl.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,sDAAsD;AACtD,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,mEAAmE;AACnE,+EAA+E;AAC/E,8EAA8E;AAC9E,oDAAoD;AACpD,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,sEAAsE;AACtE,mEAAmE;AACnE,qEAAqE;AACrE,kEAAkE;AAClE,gFAAgF;AAChF,kDAAkD;AAClD,gFAAgF;AAChF,kCAAkC;AAClC,wDAAwD;AACxD,SAAS;AACT,0EAA0E;AAC1E,2EAA2E;AAC3E,oDAAoD;AACpD,MAAM,WAAW,GAAG,kBAAkB,CAAC;AACvC,MAAM,kBAAkB,GAAG,kCAAkC,CAAC;AAC9D,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAC7C,MAAM,YAAY,GAAG,YAAY,CAAC;AAClC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAC9B,2EAA2E;AAC3E,4EAA4E;AAC5E,+EAA+E;AAC/E,4EAA4E;AAC5E,6CAA6C;AAC7C,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,uEAAuE;AACvE,+EAA+E;AAC/E,kEAAkE;AAClE,6FAA6F;AAC7F,mCAAmC;AACnC,yEAAyE;AACzE,uDAAuD;AACvD,6EAA6E;AAC7E,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAElD,6EAA6E;AAC7E,SAAS,WAAW,CAAC,IAAY,EAAE,MAAc;IAC/C,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AACtG,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACvD,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,wEAAwE;IACxE,6EAA6E;IAC7E,wEAAwE;IACxE,iEAAiE;IACjE,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1C,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC;gBAAE,KAAK,GAAG,IAAI,CAAC;YAC3C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,sEAAsE;QACtE,wDAAwD;QACxD,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC7D,KAAK,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;YACjB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9D,IAAI,IAAI,KAAK,SAAS,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7D,MAAM,GAAG,IAAI,CAAC;YACd,SAAS;QACX,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,wEAAwE;IACxE,sEAAsE;IACtE,+EAA+E;IAC/E,8EAA8E;IAC9E,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taskless-app/shared",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.42",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared types, Zod schemas and design tokens for the Taskless API contract — consumed by @taskless/api, @taskless/web and the Taskless mobile app.",
|
|
6
6
|
"license": "MIT",
|