@14ch/svelte-ui 0.0.41 → 0.0.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.
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import IconButton from './IconButton.svelte';
|
|
5
5
|
import { getStyleFromNumber } from '../utils/style';
|
|
6
6
|
import { t } from '../i18n';
|
|
7
|
-
import {
|
|
7
|
+
import { escapeHtml, convertToLink } from '../utils/formatText';
|
|
8
8
|
import type { HTMLTextareaAttributes } from 'svelte/elements';
|
|
9
9
|
import type { IconVariant, IconWeight, IconGrade, IconOpticalSize } from '../types/icon';
|
|
10
10
|
import type {
|
|
@@ -475,21 +475,14 @@
|
|
|
475
475
|
value !== null && value !== undefined && !(typeof value === 'string' && value === '')
|
|
476
476
|
);
|
|
477
477
|
|
|
478
|
-
// HTML表示用の値(
|
|
478
|
+
// HTML表示用の値(pre-wrap で表示するため HTML エスケープのみ行う)
|
|
479
479
|
const displayValue = $derived.by(() => {
|
|
480
480
|
const normalizedValue = value ?? '';
|
|
481
481
|
if (normalizedValue !== '') {
|
|
482
|
-
|
|
483
|
-
const html = String(converted ?? '');
|
|
484
|
-
// 最後の行が空だったら空白を追加(高さ調整のため)
|
|
485
|
-
const lines = html.split('<br />');
|
|
486
|
-
if (lines.length > 0 && lines[lines.length - 1] === '') {
|
|
487
|
-
return html + ' ';
|
|
488
|
-
}
|
|
489
|
-
return html;
|
|
482
|
+
return escapeHtml(normalizedValue);
|
|
490
483
|
}
|
|
491
484
|
// 値が空のとき: placeholder があればその幅・高さを確保して表示、なければ inline 時のみ
|
|
492
|
-
return placeholder ?
|
|
485
|
+
return placeholder ? escapeHtml(placeholder) : inline ? ' ' : '';
|
|
493
486
|
});
|
|
494
487
|
|
|
495
488
|
// URLをリンク化した表示用HTML(クリック検出用オーバーレイで使用)
|
|
@@ -498,8 +491,7 @@
|
|
|
498
491
|
if (!linkify || normalizedValue === '') {
|
|
499
492
|
return '';
|
|
500
493
|
}
|
|
501
|
-
|
|
502
|
-
return String(result ?? '');
|
|
494
|
+
return convertToLink(escapeHtml(normalizedValue));
|
|
503
495
|
});
|
|
504
496
|
|
|
505
497
|
// --------------------------------
|
|
@@ -631,6 +623,7 @@
|
|
|
631
623
|
position: relative;
|
|
632
624
|
width: auto;
|
|
633
625
|
max-width: 100%;
|
|
626
|
+
overflow: hidden;
|
|
634
627
|
|
|
635
628
|
&.textarea--full-height {
|
|
636
629
|
height: 100%;
|
|
@@ -699,6 +692,7 @@
|
|
|
699
692
|
transition: none;
|
|
700
693
|
overflow-y: auto;
|
|
701
694
|
overflow-x: hidden;
|
|
695
|
+
max-height: 100%;
|
|
702
696
|
|
|
703
697
|
&::before {
|
|
704
698
|
content: '';
|
|
@@ -709,13 +703,15 @@
|
|
|
709
703
|
}
|
|
710
704
|
}
|
|
711
705
|
|
|
712
|
-
/* display-text:
|
|
706
|
+
/* display-text: textarea の white-space: pre-wrap に合わせて空白・改行を同じルールで扱う */
|
|
713
707
|
.textarea__display-text {
|
|
708
|
+
white-space: pre-wrap;
|
|
714
709
|
scrollbar-color: transparent transparent;
|
|
715
710
|
}
|
|
716
711
|
|
|
717
|
-
/* link-text:
|
|
712
|
+
/* link-text: 絶対配置オーバーレイ。pre-wrap で textarea と空白・改行を同じルールで扱う */
|
|
718
713
|
.textarea__link-text {
|
|
714
|
+
white-space: pre-wrap;
|
|
719
715
|
scrollbar-width: none;
|
|
720
716
|
|
|
721
717
|
&::-webkit-scrollbar {
|
package/dist/utils/formatText.js
CHANGED
|
@@ -18,7 +18,7 @@ export const convertToHtml = (value) => {
|
|
|
18
18
|
};
|
|
19
19
|
export const convertToLink = (str) => {
|
|
20
20
|
let text = str;
|
|
21
|
-
text = text.replace(/((http|https|ftp):\/\/[\w?=&./#~%-;,*!$'():@+]+(?![\w\s?&./#~%";,=*'()-]*>))/g, '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>
|
|
21
|
+
text = text.replace(/((http|https|ftp):\/\/[\w?=&./#~%-;,*!$'():@+]+(?![\w\s?&./#~%";,=*'()-]*>))/g, '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>');
|
|
22
22
|
return text;
|
|
23
23
|
};
|
|
24
24
|
export const escapeHtml = (value) => {
|