Merge remote-tracking branch 'origin/sub_laptop_8' into main_laptop_1

This commit is contained in:
2026-09-28 14:41:14 +09:00
4 changed files with 92 additions and 0 deletions
@@ -405,6 +405,25 @@ export function parseClipboard(html: string, text: string, at: CellAddress): Cli
return null;
}
const NO_FORMULA_NOTIFIED_KEY = "aislo-ss-notified-no-formula";
/** 붙인 뭉치 어디에도 수식(`식`)이 없음 — 엑셀 HTML 클립보드는 「수식 표시」(Ctrl+`) 없이 복사하면
* 계산값만 실림(수식 자체는 절대 안 실림). */
function hasNoFormula(block: ClipBlock): boolean {
return !Object.values(block.칸).some((cell) => cell.식 !== undefined);
}
/** 세션에 한 번만 — 엑셀에서 값만 온 붙여넣기마다 매번 뜨면 성가심. */
function notifyNoFormulaOnce(): void {
try {
if (sessionStorage.getItem(NO_FORMULA_NOTIFIED_KEY)) return;
sessionStorage.setItem(NO_FORMULA_NOTIFIED_KEY, "1");
} catch {
// 세션 저장 안 되면 매번 뜰 수 있으나 치명적이지 않음.
}
showToast(st("ClipboardExcelNoFormula"));
}
/* ── 화면 붙임 — copy · cut · paste 사건 ────────────────────────────────── */
function activeRange(ctx: SpreadsheetContext): CellRange {
@@ -525,6 +544,7 @@ export function attachClipboard(ctx: SpreadsheetContext): PartHandle {
return;
}
ev.preventDefault();
if (block.출처 === "excel" && hasNoFormula(block)) notifyNoFormulaOnce();
pasteBlock(ctx, block, at);
}
@@ -103,6 +103,23 @@ const TEXT = {
UnitGroup_op: ["연산·비교", "Operators"],
UnitRecent: ["최근 씀", "Recently used"],
UnitAsFormat: ["숫자 형식으로 붙이기", "Attach as number format"],
FormulaHint_label: [
"엑셀 수식까지: 엑셀에서 Ctrl+` → 복사 → 여기 Ctrl+V · 끝나면 엑셀 Ctrl+` 다시",
"Formulas too: in Excel Ctrl+` → copy → paste here (Ctrl+V) · then Ctrl+` again in Excel",
],
FormulaHint_title: ["엑셀 수식까지 옮기는 법", "How to bring formulas along"],
FormulaHint_detail: [
"엑셀 Ctrl+` = 「수식 표시」 켜기 · 칸에 계산값 대신 「=...」 글이 그대로 보임. 그 상태로 복사해 " +
"여기 붙이면 수식까지 옮겨짐(그냥 복사하면 값만 옴 · 수식 없음). 붙인 뒤 엑셀에서 Ctrl+` 다시 " +
"눌러 원래대로.",
'Excel Ctrl+` turns on "Show Formulas" — cells show "=..." text instead of the computed ' +
"value. Copy in that state and paste here to bring the formulas along (a normal copy only " +
"brings values). Press Ctrl+` again in Excel afterward to switch back.",
],
ClipboardExcelNoFormula: [
"값만 들어왔음 — 수식까지는 엑셀 Ctrl+` 뒤 복사",
"Only values came in — for formulas too, copy after Ctrl+` in Excel",
],
} as const;
export function st(key: keyof typeof TEXT): string {
@@ -145,6 +145,40 @@
padding: 4px 2px;
}
.ss-toolbar__hint {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
margin-left: auto;
max-width: 320px;
}
.ss-toolbar__formula-hint {
border: 0;
padding: 0;
background: none;
color: var(--color-text-muted);
font-size: 0.72rem;
text-align: right;
opacity: 0.6;
cursor: pointer;
}
.ss-toolbar__formula-hint:hover {
opacity: 1;
}
.ss-toolbar__formula-hint-detail {
color: var(--color-text-muted);
font-size: 0.68rem;
text-align: right;
}
.ss-toolbar__formula-hint-detail[hidden] {
display: none;
}
/* ── 시트 탭 ─────────────────────────────────────────────────────────────── */
.ss-tabs {
@@ -452,6 +452,26 @@ export function mountToolbar(ctx: SpreadsheetContext): PartHandle {
};
document.addEventListener("click", closeUnitPop);
// ── 엑셀 수식 복사 안내(오른쪽 위 흐린 글씨 · 누르면 두세 줄 설명) ─────────
const formulaHintBtn = el("button", {
className: "ss-toolbar__formula-hint",
attrs: { type: "button", title: st("FormulaHint_title") },
text: st("FormulaHint_label"),
});
const formulaHintDetail = el("div", {
className: "ss-toolbar__formula-hint-detail",
attrs: { hidden: "true" },
text: st("FormulaHint_detail"),
});
formulaHintBtn.addEventListener("click", (ev) => {
ev.stopPropagation();
formulaHintDetail.hidden = !formulaHintDetail.hidden;
});
const formulaHint = el("div", {
className: "ss-toolbar__hint",
children: [formulaHintBtn, formulaHintDetail],
});
root.append(
group(undoBtn, redoBtn),
group(fontInput, sizeInput),
@@ -462,6 +482,7 @@ export function mountToolbar(ctx: SpreadsheetContext): PartHandle {
group(borderBtn, borderPop),
group(numfmtInput),
group(unitBtn, unitPop),
formulaHint,
);
function refresh(): void {