anki/ts/import-csv/lib.ts
RumovZ 6da5e5b042
CSV import/export fixes and features (#1898)
* Fix footer moving upwards

* Fix column detection

Was broken because escaped line breaks were not considered.
Also removes delimiter detection on `#columns:` line. User must use tabs
or set delimiter beforehand.

* Add CSV preview

* Parse `#tags column:`

* Optionally export deck and notetype with CSV

* Avoid clones in CSV export

* Prevent bottom of page appearing under footer (dae)

* Increase padding to 1em (dae)

With 0.5em, when a vertical scrollbar is shown, it sits right next to
the right edge of the content, making it look like there's no right
margin.

* Experimental changes to make table fit+scroll (dae)

- limit individual cells to 15em, and show ellipses when truncated
- limit total table width to body width, so that inner table is shown
with scrollbar
- use class rather than id - ids are bad practice in Svelte components,
as more than one may be displayed on a single page

* Skip importing foreign notes with filtered decks

Were implicitly imported into the default deck before.
Also some refactoring to fetch deck ids and names beforehand.

* Hide spacer below hidden field mapping

* Fix guid being replaced when updating note

* Fix dupe identity check

Canonify tags before checking if dupe is identical, but only add update
tags later if appropriate.

* Fix deck export for notes with missing card 1

* Fix note lines starting with `#`

csv crate doesn't support escaping a leading comment char. :(

* Support import/export of guids

* Strip HTML from preview rows

* Fix initially set deck if current is filtered

* Make isHtml toggle reactive

* Fix `html_to_text_line()` stripping sound names

* Tweak export option labels

* Switch to patched rust-csv fork

Fixes writing lines starting with `#`, so revert 5ece10ad05f331.

* List column options with first column field

* Fix flag for exports with HTML stripped
2022-06-09 10:28:01 +10:00

82 lines
2.3 KiB
TypeScript

// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import * as tr from "../lib/ftl";
import {
ImportExport,
importExport,
Notetypes,
notetypes as notetypeService,
} from "../lib/proto";
export interface ColumnOption {
label: string;
shortLabel?: string;
value: number;
disabled: boolean;
}
export function getColumnOptions(
columnLabels: string[],
firstRow: string[],
notetypeColumn: number | null,
deckColumn: number | null,
tagsColumn: number,
guidColumn: number,
): ColumnOption[] {
return [{ label: tr.changeNotetypeNothing(), value: 0, disabled: false }].concat(
columnLabels.map((label, index) => {
index += 1;
if (index === notetypeColumn) {
return columnOption(tr.notetypesNotetype(), true, index);
} else if (index === deckColumn) {
return columnOption(tr.decksDeck(), true, index);
} else if (index === guidColumn) {
return columnOption("GUID", true, index);
} else if (index === tagsColumn) {
return columnOption(tr.editingTags(), false, index);
} else if (label === "") {
return columnOption(firstRow[index - 1], false, index, true);
} else {
return columnOption(label, false, index);
}
}),
);
}
function columnOption(
label: string,
disabled: boolean,
index: number,
shortLabel?: boolean,
): ColumnOption {
return {
label: label ? `${index}: ${label}` : index.toString(),
shortLabel: shortLabel ? index.toString() : undefined,
value: index,
disabled,
};
}
export async function getNotetypeFields(notetypeId: number): Promise<string[]> {
return notetypeService
.getFieldNames(Notetypes.NotetypeId.create({ ntid: notetypeId }))
.then((list) => list.vals);
}
export async function getCsvMetadata(
path: string,
delimiter?: ImportExport.CsvMetadata.Delimiter,
notetypeId?: number,
isHtml?: boolean,
): Promise<ImportExport.CsvMetadata> {
return importExport.getCsvMetadata(
ImportExport.CsvMetadataRequest.create({
path,
delimiter,
notetypeId,
isHtml,
}),
);
}