fix: release problem

This commit is contained in:
leijun 2023-08-28 14:58:37 +08:00
parent 0b6b3d4712
commit dd0f5348e2
11 changed files with 654 additions and 2354 deletions

View file

@ -11,8 +11,12 @@ If you are using Microsoft Office 365 to create xlsx files, you need to import t
![import](./doc/img/import.gif)
### embed link to markdown
## TODO
- link to markdown
![link](./doc/img/link.gif)
### E-mail
- ljcoder@163.com

83
main.ts
View file

@ -3,19 +3,13 @@ import {
Plugin,
WorkspaceLeaf,
normalizePath,
MenuItem,
Menu,
} from "obsidian";
import { ExcelSettings, DEFAULT_SETTINGS } from "./src/utils/Settings";
import {
emulateCTRLClickForLinks,
linkClickModifierType,
PaneTarget,
} from "./src/utils/ModifierkeyHelper";
import { ExcelView, VIEW_TYPE_EXCEL } from "./src/ExcelView";
import {
checkAndCreateFolder,
getNewUniqueFilepath,
getExcelFilename,
} from "./src/utils/FileUtils";
@ -24,8 +18,6 @@ import {
markdownPostProcessor,
} from "./src/MarkdownPostProcessor";
declare const PLUGIN_VERSION: string;
export default class ExcelPlugin extends Plugin {
public settings: ExcelSettings;
@ -37,7 +29,7 @@ export default class ExcelPlugin extends Plugin {
this.registerExtensions(["sheet"], VIEW_TYPE_EXCEL);
// This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon(
this.addRibbonIcon(
"table",
"Excel",
(e: MouseEvent) => {
@ -46,71 +38,8 @@ export default class ExcelPlugin extends Plugin {
}
);
// TODO markdwon后处理
// markdwon后处理
this.addMarkdownPostProcessor();
// TODO 链接处理
// this.registerCommand();
}
private registerCommand() {
const fileMenuHandlerConvertKeepExtension = (
menu: Menu,
file: TFile
) => {
console.log("fileMenuHandlerConvertKeepExtension");
if (file instanceof TFile && file.extension == "excel") {
menu.addItem((item: MenuItem) => {
item.setTitle("*.xlsx => *.xlsx.md").onClick(() => {
this.convertSingleExcalidrawToMD(file, false, false);
});
});
}
};
this.registerEvent(
this.app.workspace.on(
"file-menu",
fileMenuHandlerConvertKeepExtension
)
);
}
public async convertSingleExcalidrawToMD(
file: TFile,
replaceExtension: boolean = false,
keepOriginal: boolean = false
): Promise<TFile> {
const data = await this.app.vault.read(file);
const filename =
file.name.substring(0, file.name.lastIndexOf(".xlsx")) +
(replaceExtension ? ".md" : ".xlsx.md");
const fname = getNewUniqueFilepath(
this.app.vault,
filename,
normalizePath(
file.path.substring(0, file.path.lastIndexOf(file.name))
)
);
const result = await this.app.vault.create(fname, "{}");
// if (this.settings.keepInSync) {
// EXPORT_TYPES.forEach((ext: string) => {
// const oldIMGpath =
// file.path.substring(0, file.path.lastIndexOf(".xlsx")) + ext;
// const imgFile = this.app.vault.getAbstractFileByPath(
// normalizePath(oldIMGpath),
// );
// if (imgFile && imgFile instanceof TFile) {
// const newIMGpath = fname.substring(0, fname.lastIndexOf(".md")) + ext;
// this.app.fileManager.renameFile(imgFile, newIMGpath);
// }
// });
// }
// if (!keepOriginal) {
// this.app.vault.delete(file);
// }
return result;
}
private addMarkdownPostProcessor() {
@ -160,7 +89,7 @@ export default class ExcelPlugin extends Plugin {
public openExcel(
excelFile: TFile,
location: PaneTarget,
active: boolean = false,
active = false,
subpath?: string
) {
if (location === "md-properties") {
@ -168,10 +97,10 @@ export default class ExcelPlugin extends Plugin {
}
var leaf: WorkspaceLeaf | null = null;
if (location === "popout-window") {
leaf = app.workspace.openPopoutLeaf();
leaf = this.app.workspace.openPopoutLeaf();
}
if (location === "new-tab") {
leaf = app.workspace.getLeaf("tab");
leaf = this.app.workspace.getLeaf("tab");
}
if (!leaf) {
leaf = this.app.workspace.getLeaf(false);
@ -179,7 +108,7 @@ export default class ExcelPlugin extends Plugin {
leaf.view.getViewType() !== "empty" &&
location === "new-pane"
) {
leaf = app.workspace.getMostRecentLeaf();
leaf = this.app.workspace.getMostRecentLeaf();
}
}

View file

@ -1,11 +1,10 @@
{
"id": "excel",
"name": "Excel",
"version": "1.1.2",
"version": "1.2.1",
"minAppVersion": "0.15.0",
"description": "This is a Excel plugin for Obsidian.",
"description": "Create spreadsheets and easily embed them in Markdown",
"author": "ljcoder",
"authorUrl": "https://github.com/ljcoder2015",
"fundingUrl": "https://github.com/ljcoder2015/obsidian-excel",
"isDesktopOnly": false
}

2558
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,9 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@codemirror/language": "^6.9.0",
"@codemirror/state": "^6.2.1",
"@codemirror/view": "^6.16.0",
"@hyrious/esbuild-plugin-svgo": "^0.2.0",
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "5.29.0",

View file

@ -34,57 +34,5 @@ export class Excel extends MarkdownRenderChild {
// @ts-ignore
sheet.validate();
// const sheetIframe = this.containerEl.createEl("iframe", {
// cls: "sheet-iframe",
// });
// var document = sheetIframe.contentDocument
// if (document) {
// // 原生插入div
// const sheetDiv = document.createElement("div");
// sheetDiv.id = "x-spreadsheet";
// document.body.appendChild(sheetDiv);
// // <link rel="stylesheet" href="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.css">
// // <script src="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.js"></script>
// const cssEl = document.createElement('link')
// cssEl.rel = 'stylesheet'
// cssEl.href = 'https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.css'
// document.head.appendChild(cssEl)
// const scritpLinkEl = document.createElement('script')
// scritpLinkEl.lang = 'javascript';
// scritpLinkEl.type = 'text/javascript';
// scritpLinkEl.text = Spreadsheet.toString()
// document.body.appendChild(scritpLinkEl)
// console.log(scritpLinkEl, '-----')
// const scriptString = `
// const s = x_spreadsheet("#x-spreadsheet", {
// mode: "read",
// view: {
// height: () => ${this.containerEl.clientHeight},
// width: () => 300,
// },
// }).loadData(${this.data});
// s.validate();
// `;
// const sEl = document.createElement("script");
// sEl.text = scriptString;
// document.body.appendChild(sEl);
// }
// console.log(
// "sheetIframe",
// sheetIframe
// );
// this.containerEl.replaceWith(sheetIframe);
}
}

45
src/ExcelField.ts Normal file
View file

@ -0,0 +1,45 @@
import { syntaxTree } from "@codemirror/language";
import {
Extension,
RangeSetBuilder,
StateField,
Transaction,
} from "@codemirror/state";
import {
Decoration,
DecorationSet,
EditorView,
} from "@codemirror/view";
import { ExcelWidget } from "./ExcelWidget";
export const ExcelField = StateField.define<DecorationSet>({
create(state): DecorationSet {
return Decoration.none;
},
update(oldState: DecorationSet, transaction: Transaction): DecorationSet {
const builder = new RangeSetBuilder<Decoration>();
syntaxTree(transaction.state).iterate({
enter(node) {
console.log(node)
// if (node.type.name.startsWith("list")) {
// // Position of the '-' or the '*'.
// const listCharFrom = node.from - 2;
// builder.add(
// listCharFrom,
// listCharFrom + 1,
// Decoration.replace({
// widget: new EmojiWidget(),
// })
// );
// }
},
});
return builder.finish();
},
provide(field: StateField<DecorationSet>): Extension {
return EditorView.decorations.from(field);
},
});

37
src/ExcelWidget.ts Normal file
View file

@ -0,0 +1,37 @@
import { EditorView, WidgetType } from "@codemirror/view"
import Spreadsheet from "x-data-spreadsheet";
export class ExcelWidget extends WidgetType {
data: string
constructor(data: string) {
super()
this.data = data
}
toDOM(view: EditorView): HTMLElement {
const time = new Date().getTime()
const sheetEle = document.createDiv({
cls: 'sheet-iframe',
attr: {
id: `x-spreadsheet-${time}`,
},
});
const jsonData = JSON.parse(this.data || "{}") || {};
//@ts-ignore
const sheet = new Spreadsheet(sheetEle, {
mode: "read",
showToolbar: false,
showBottomBar: true,
view: {
height: () => 300,
width: () => document.body.clientWidth,
},
}).loadData(jsonData); // load data
// @ts-ignore
sheet.validate();
return sheetEle
}
}

View file

@ -1,8 +1,8 @@
import {
MarkdownPostProcessorContext,
MetadataCache,
TFile,
Vault,
MarkdownPostProcessorContext,
MetadataCache,
TFile,
Vault,
} from "obsidian";
import ExcelPlugin from "../main";
import { Excel } from "./Excel";
@ -12,9 +12,79 @@ let vault: Vault;
let metadataCache: MetadataCache;
export const initializeMarkdownPostProcessor = (p: ExcelPlugin) => {
plugin = p;
vault = p.app.vault;
metadataCache = p.app.metadataCache;
plugin = p;
vault = p.app.vault;
metadataCache = p.app.metadataCache;
};
// 编辑模式
const tmpObsidianWYSIWYG = async (
el: HTMLElement,
ctx: MarkdownPostProcessorContext
) => {
const file = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
console.log('tmpObsidianWYSIWYG',file, el, ctx.sourcePath)
if (!(file instanceof TFile)) return;
if (!plugin.isExcelFile(file)) return;
//@ts-ignore
if (ctx.remainingNestLevel < 4) {
return;
}
//internal-embed: Excalidraw is embedded into a markdown document
//markdown-reading-view: we are processing the markdown reading view of an actual Excalidraw file
//markdown-embed: we are processing the hover preview of a markdown file
//alt, width, and height attributes of .internal-embed to size and style the image
//@ts-ignore
const containerEl = ctx.containerEl;
let internalEmbedDiv: HTMLElement = containerEl;
while (
!internalEmbedDiv.hasClass("dataview") &&
!internalEmbedDiv.hasClass("cm-preview-code-block") &&
!internalEmbedDiv.hasClass("cm-embed-block") &&
!internalEmbedDiv.hasClass("internal-embed") &&
!internalEmbedDiv.hasClass("markdown-reading-view") &&
!internalEmbedDiv.hasClass("markdown-embed") &&
internalEmbedDiv.parentElement
) {
internalEmbedDiv = internalEmbedDiv.parentElement;
}
if (
internalEmbedDiv.hasClass("dataview") ||
internalEmbedDiv.hasClass("cm-preview-code-block") ||
internalEmbedDiv.hasClass("cm-embed-block")
) {
return; //https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/835
}
const markdownEmbed = internalEmbedDiv.hasClass("markdown-embed");
const markdownReadingView = internalEmbedDiv.hasClass(
"markdown-reading-view"
);
if (
!internalEmbedDiv.hasClass("internal-embed") &&
(markdownEmbed || markdownReadingView)
) {
//We are processing the markdown preview of an actual Excalidraw file
//the excalidraw file in markdown preview mode
const isFrontmatterDiv = Boolean(el.querySelector(".frontmatter"));
el.empty();
internalEmbedDiv.empty();
const data = await vault.read(file);
const excel = new Excel(el, data, new Date().getTime());
ctx.addChild(excel);
}
el.empty();
internalEmbedDiv.empty();
const data = await vault.read(file);
const excel = new Excel(el, data, 0);
ctx.addChild(excel);
};
/**
@ -23,51 +93,51 @@ export const initializeMarkdownPostProcessor = (p: ExcelPlugin) => {
* @param ctx
*/
export const markdownPostProcessor = async (
el: HTMLElement,
ctx: MarkdownPostProcessorContext,
el: HTMLElement,
ctx: MarkdownPostProcessorContext
) => {
//check to see if we are rendering in editing mode or live preview
//if yes, then there should be no .internal-embed containers
const embeddedItems = el.querySelectorAll(".internal-embed");
if (embeddedItems.length === 0) {
return;
}
console.log('markdownPostProcessor', el)
//check to see if we are rendering in editing mode or live preview
//if yes, then there should be no .internal-embed containers
const embeddedItems = el.querySelectorAll(".internal-embed");
if (embeddedItems.length === 0) {
return;
}
await processReadingMode(embeddedItems, ctx);
await processReadingMode(embeddedItems, ctx);
};
const processReadingMode = async (
embeddedItems: NodeListOf<Element> | [HTMLElement],
ctx: MarkdownPostProcessorContext,
embeddedItems: NodeListOf<Element> | [HTMLElement],
ctx: MarkdownPostProcessorContext
) => {
//We are processing a non-excalidraw file in reading mode
//Embedded files will be displayed in an .internal-embed container
//We are processing a non-excalidraw file in reading mode
//Embedded files will be displayed in an .internal-embed container
//Iterating all the containers in the file to check which one is an excalidraw drawing
//This is a for loop instead of embeddedItems.forEach() because processInternalEmbed at the end
//is awaited, otherwise excalidraw images would not display in the Kanban plugin
embeddedItems.forEach(async (maybeDrawing, index) => {
//check to see if the file in the src attribute exists
console.log(maybeDrawing)
const fname = maybeDrawing.getAttribute("src")?.split("#")[0];
if(!fname) return true;
//Iterating all the containers in the file to check which one is an excalidraw drawing
//This is a for loop instead of embeddedItems.forEach() because processInternalEmbed at the end
//is awaited, otherwise excalidraw images would not display in the Kanban plugin
embeddedItems.forEach(async (maybeDrawing, index) => {
//check to see if the file in the src attribute exists
console.log(maybeDrawing);
const fname = maybeDrawing.getAttribute("src")?.split("#")[0];
if (!fname) return true;
const file = metadataCache.getFirstLinkpathDest(fname, ctx.sourcePath);
console.log('forEach', file, ctx.sourcePath)
const file = metadataCache.getFirstLinkpathDest(fname, ctx.sourcePath);
console.log("forEach", file, ctx.sourcePath);
//if the embeddedFile exits and it is an Excalidraw file
//then lets replace the .internal-embed with the generated PNG or SVG image
if (file && file instanceof TFile && plugin.isExcelFile(file)) {
const data = await vault.read(file)
const parent = maybeDrawing.parentElement
if (data && parent) {
const excel = new Excel(maybeDrawing.parentElement, data, index)
ctx.addChild(excel)
}
}
})
//if the embeddedFile exits and it is an Excalidraw file
//then lets replace the .internal-embed with the generated PNG or SVG image
if (file && file instanceof TFile && plugin.isExcelFile(file)) {
const data = await vault.read(file);
const parent = maybeDrawing.parentElement;
if (data && parent) {
const excel = new Excel(
maybeDrawing.parentElement,
data,
index
);
ctx.addChild(excel);
}
}
});
};

View file

@ -1,53 +1,4 @@
export type PaneTarget = "active-pane"|"new-pane"|"popout-window"|"new-tab"|"md-properties";
export type ModifierKeys = {shiftKey:boolean, ctrlKey: boolean, metaKey: boolean, altKey: boolean};
export type KeyEvent = PointerEvent | MouseEvent | KeyboardEvent | ModifierKeys;
export type DeviceType = {
isDesktop: boolean,
isPhone: boolean,
isTablet: boolean,
isMobile: boolean,
isLinux: boolean,
isMacOS: boolean,
isWindows: boolean,
isIOS: boolean,
isAndroid: boolean
};
export const DEVICE: DeviceType = {
isDesktop: !document.body.hasClass("is-tablet") && !document.body.hasClass("is-mobile"),
isPhone: document.body.hasClass("is-phone"),
isTablet: document.body.hasClass("is-tablet"),
isMobile: document.body.hasClass("is-mobile"), //running Obsidian Mobile, need to also check isTablet
isLinux: document.body.hasClass("mod-linux") && ! document.body.hasClass("is-android"),
isMacOS: document.body.hasClass("mod-macos") && ! document.body.hasClass("is-ios"),
isWindows: document.body.hasClass("mod-windows"),
isIOS: document.body.hasClass("is-ios"),
isAndroid: document.body.hasClass("is-android")
};
export const isCTRL = (e:KeyEvent) => DEVICE.isIOS || DEVICE.isMacOS ? e.metaKey : e.ctrlKey;
export const isALT = (e:KeyEvent) => e.altKey;
export const isMETA = (e:KeyEvent) => DEVICE.isIOS || DEVICE.isMacOS ? e.ctrlKey : e.metaKey;
export const isSHIFT = (e:KeyEvent) => e.shiftKey;
export const mdPropModifier = (ev: KeyEvent): boolean => !isSHIFT(ev) && isCTRL(ev) && !isALT(ev) && isMETA(ev);
export const emulateCTRLClickForLinks = (e: KeyEvent) => {
return {
shiftKey: e.shiftKey,
ctrlKey: e.ctrlKey || !(DEVICE.isIOS || DEVICE.isMacOS),
metaKey: e.metaKey || (DEVICE.isIOS || DEVICE.isMacOS),
altKey: e.altKey
}
}
export const linkClickModifierType = (ev: KeyEvent):PaneTarget => {
if(isCTRL(ev) && !isALT(ev) && isSHIFT(ev) && !isMETA(ev)) return "active-pane";
if(isCTRL(ev) && !isALT(ev) && !isSHIFT(ev) && !isMETA(ev)) return "new-tab";
if(isCTRL(ev) && isALT(ev) && !isSHIFT(ev) && !isMETA(ev)) return "new-pane";
if(DEVICE.isDesktop && isCTRL(ev) && isALT(ev) && isSHIFT(ev) && !isMETA(ev) ) return "popout-window";
if(isCTRL(ev) && isALT(ev) && isSHIFT(ev) && !isMETA(ev)) return "new-tab";
if(mdPropModifier(ev)) return "md-properties";
return "active-pane";
}
export type KeyEvent = PointerEvent | MouseEvent | KeyboardEvent | ModifierKeys;

View file

@ -1,9 +1,9 @@
export interface ExcelSettings {
folder: string;
excelFilenamePrefix: String,
excelFilenamePrefix: string,
excelEmbedPrefixWithFilename: true,
excelFilnameEmbedPostfix: String,
excelFilenameDateTime: String,
excelFilnameEmbedPostfix: string,
excelFilenameDateTime: string,
}
export const DEFAULT_SETTINGS: ExcelSettings = {