9.19
This commit is contained in:
4
.obsidian/app.json
vendored
4
.obsidian/app.json
vendored
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"promptDelete": false
|
"promptDelete": false,
|
||||||
|
"showLineNumber": true,
|
||||||
|
"readableLineLength": true
|
||||||
}
|
}
|
||||||
3
.obsidian/appearance.json
vendored
3
.obsidian/appearance.json
vendored
@@ -4,5 +4,6 @@
|
|||||||
"enabledCssSnippets": [
|
"enabledCssSnippets": [
|
||||||
"jindutiao"
|
"jindutiao"
|
||||||
],
|
],
|
||||||
"nativeMenus": false
|
"nativeMenus": false,
|
||||||
|
"showViewHeader": true
|
||||||
}
|
}
|
||||||
4
.obsidian/community-plugins.json
vendored
4
.obsidian/community-plugins.json
vendored
@@ -10,5 +10,7 @@
|
|||||||
"obsidian-image-auto-upload-plugin",
|
"obsidian-image-auto-upload-plugin",
|
||||||
"obsidian-git",
|
"obsidian-git",
|
||||||
"obsidian-importer",
|
"obsidian-importer",
|
||||||
"obsidian-style-settings"
|
"obsidian-style-settings",
|
||||||
|
"obsidian-link-embed",
|
||||||
|
"obsidian-auto-link-title"
|
||||||
]
|
]
|
||||||
2
.obsidian/core-plugins.json
vendored
2
.obsidian/core-plugins.json
vendored
@@ -27,7 +27,7 @@
|
|||||||
"file-recovery": true,
|
"file-recovery": true,
|
||||||
"publish": false,
|
"publish": false,
|
||||||
"sync": false,
|
"sync": false,
|
||||||
"webviewer": false,
|
"webviewer": true,
|
||||||
"footnotes": false,
|
"footnotes": false,
|
||||||
"bases": true
|
"bases": true
|
||||||
}
|
}
|
||||||
771
.obsidian/plugins/obsidian-auto-link-title/main.js
vendored
Normal file
771
.obsidian/plugins/obsidian-auto-link-title/main.js
vendored
Normal file
@@ -0,0 +1,771 @@
|
|||||||
|
/*
|
||||||
|
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
|
||||||
|
if you want to view the source visit the plugins github repository
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var obsidian = require('obsidian');
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
***************************************************************************** */
|
||||||
|
|
||||||
|
function __awaiter(thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
||||||
|
var e = new Error(message);
|
||||||
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_SETTINGS = {
|
||||||
|
regex: /^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})$/i,
|
||||||
|
lineRegex: /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/gi,
|
||||||
|
linkRegex: /^\[([^\[\]]*)\]\((https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})\)$/i,
|
||||||
|
linkLineRegex: /\[([^\[\]]*)\]\((https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})\)/gi,
|
||||||
|
imageRegex: /\.(gif|jpe?g|tiff?|png|webp|bmp|tga|psd|ai)$/i,
|
||||||
|
enhanceDefaultPaste: true,
|
||||||
|
shouldPreserveSelectionAsTitle: false,
|
||||||
|
enhanceDropEvents: true,
|
||||||
|
websiteBlacklist: "",
|
||||||
|
maximumTitleLength: 0,
|
||||||
|
useNewScraper: false,
|
||||||
|
linkPreviewApiKey: "",
|
||||||
|
useBetterPasteId: false,
|
||||||
|
};
|
||||||
|
class AutoLinkTitleSettingTab extends obsidian.PluginSettingTab {
|
||||||
|
constructor(app, plugin) {
|
||||||
|
super(app, plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
display() {
|
||||||
|
let { containerEl } = this;
|
||||||
|
containerEl.empty();
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Enhance Default Paste")
|
||||||
|
.setDesc("Fetch the link title when pasting a link in the editor with the default paste command")
|
||||||
|
.addToggle((val) => val
|
||||||
|
.setValue(this.plugin.settings.enhanceDefaultPaste)
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
console.log(value);
|
||||||
|
this.plugin.settings.enhanceDefaultPaste = value;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
})));
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Enhance Drop Events")
|
||||||
|
.setDesc("Fetch the link title when drag and dropping a link from another program")
|
||||||
|
.addToggle((val) => val
|
||||||
|
.setValue(this.plugin.settings.enhanceDropEvents)
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
console.log(value);
|
||||||
|
this.plugin.settings.enhanceDropEvents = value;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
})));
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Maximum title length")
|
||||||
|
.setDesc("Set the maximum length of the title. Set to 0 to disable.")
|
||||||
|
.addText((val) => val
|
||||||
|
.setValue(this.plugin.settings.maximumTitleLength.toString(10))
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const titleLength = Number(value);
|
||||||
|
this.plugin.settings.maximumTitleLength =
|
||||||
|
isNaN(titleLength) || titleLength < 0 ? 0 : titleLength;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
})));
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Preserve selection as title")
|
||||||
|
.setDesc("Whether to prefer selected text as title over fetched title when pasting")
|
||||||
|
.addToggle((val) => val
|
||||||
|
.setValue(this.plugin.settings.shouldPreserveSelectionAsTitle)
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
console.log(value);
|
||||||
|
this.plugin.settings.shouldPreserveSelectionAsTitle = value;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
})));
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Website Blacklist")
|
||||||
|
.setDesc("List of strings (comma separated) that disable autocompleting website titles. Can be URLs or arbitrary text.")
|
||||||
|
.addTextArea((val) => val
|
||||||
|
.setValue(this.plugin.settings.websiteBlacklist)
|
||||||
|
.setPlaceholder("localhost, tiktok.com")
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
this.plugin.settings.websiteBlacklist = value;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
})));
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Use New Scraper")
|
||||||
|
.setDesc("Use experimental new scraper, seems to work well on desktop but not mobile.")
|
||||||
|
.addToggle((val) => val
|
||||||
|
.setValue(this.plugin.settings.useNewScraper)
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
console.log(value);
|
||||||
|
this.plugin.settings.useNewScraper = value;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
})));
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("Use Better Fetching Placeholder")
|
||||||
|
.setDesc("Use a more readable placeholder when fetching the title of a link.")
|
||||||
|
.addToggle((val) => val
|
||||||
|
.setValue(this.plugin.settings.useBetterPasteId)
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
console.log(value);
|
||||||
|
this.plugin.settings.useBetterPasteId = value;
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
})));
|
||||||
|
new obsidian.Setting(containerEl)
|
||||||
|
.setName("LinkPreview API Key")
|
||||||
|
.setDesc("API key for the LinkPreview.net service. Get one at https://my.linkpreview.net/access_keys")
|
||||||
|
.addText((text) => text
|
||||||
|
.setValue(this.plugin.settings.linkPreviewApiKey || "")
|
||||||
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const trimmedValue = value.trim();
|
||||||
|
if (trimmedValue.length > 0 && trimmedValue.length !== 32) {
|
||||||
|
new obsidian.Notice("LinkPreview API key must be 32 characters long");
|
||||||
|
this.plugin.settings.linkPreviewApiKey = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.plugin.settings.linkPreviewApiKey = trimmedValue;
|
||||||
|
}
|
||||||
|
yield this.plugin.saveSettings();
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CheckIf {
|
||||||
|
static isMarkdownLinkAlready(editor) {
|
||||||
|
let cursor = editor.getCursor();
|
||||||
|
// Check if the characters before the url are ]( to indicate a markdown link
|
||||||
|
var titleEnd = editor.getRange({ ch: cursor.ch - 2, line: cursor.line }, { ch: cursor.ch, line: cursor.line });
|
||||||
|
return titleEnd == "](";
|
||||||
|
}
|
||||||
|
static isAfterQuote(editor) {
|
||||||
|
let cursor = editor.getCursor();
|
||||||
|
// Check if the characters before the url are " or ' to indicate we want the url directly
|
||||||
|
// This is common in elements like <a href="linkhere"></a>
|
||||||
|
var beforeChar = editor.getRange({ ch: cursor.ch - 1, line: cursor.line }, { ch: cursor.ch, line: cursor.line });
|
||||||
|
return beforeChar == "\"" || beforeChar == "'";
|
||||||
|
}
|
||||||
|
static isUrl(text) {
|
||||||
|
let urlRegex = new RegExp(DEFAULT_SETTINGS.regex);
|
||||||
|
return urlRegex.test(text);
|
||||||
|
}
|
||||||
|
static isImage(text) {
|
||||||
|
let imageRegex = new RegExp(DEFAULT_SETTINGS.imageRegex);
|
||||||
|
return imageRegex.test(text);
|
||||||
|
}
|
||||||
|
static isLinkedUrl(text) {
|
||||||
|
let urlRegex = new RegExp(DEFAULT_SETTINGS.linkRegex);
|
||||||
|
return urlRegex.test(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditorExtensions {
|
||||||
|
static getSelectedText(editor) {
|
||||||
|
if (!editor.somethingSelected()) {
|
||||||
|
let wordBoundaries = this.getWordBoundaries(editor);
|
||||||
|
editor.setSelection(wordBoundaries.start, wordBoundaries.end);
|
||||||
|
}
|
||||||
|
return editor.getSelection();
|
||||||
|
}
|
||||||
|
static cursorWithinBoundaries(cursor, match) {
|
||||||
|
let startIndex = match.index;
|
||||||
|
let endIndex = match.index + match[0].length;
|
||||||
|
return startIndex <= cursor.ch && cursor.ch <= endIndex;
|
||||||
|
}
|
||||||
|
static getWordBoundaries(editor) {
|
||||||
|
let cursor = editor.getCursor();
|
||||||
|
// If its a normal URL token this is not a markdown link
|
||||||
|
// In this case we can simply overwrite the link boundaries as-is
|
||||||
|
let lineText = editor.getLine(cursor.line);
|
||||||
|
// First check if we're in a link
|
||||||
|
let linksInLine = lineText.matchAll(DEFAULT_SETTINGS.linkLineRegex);
|
||||||
|
for (let match of linksInLine) {
|
||||||
|
if (this.cursorWithinBoundaries(cursor, match)) {
|
||||||
|
return {
|
||||||
|
start: { line: cursor.line, ch: match.index },
|
||||||
|
end: { line: cursor.line, ch: match.index + match[0].length },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If not, check if we're in just a standard ol' URL.
|
||||||
|
let urlsInLine = lineText.matchAll(DEFAULT_SETTINGS.lineRegex);
|
||||||
|
for (let match of urlsInLine) {
|
||||||
|
if (this.cursorWithinBoundaries(cursor, match)) {
|
||||||
|
return {
|
||||||
|
start: { line: cursor.line, ch: match.index },
|
||||||
|
end: { line: cursor.line, ch: match.index + match[0].length },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
start: cursor,
|
||||||
|
end: cursor,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static getEditorPositionFromIndex(content, index) {
|
||||||
|
let substr = content.substr(0, index);
|
||||||
|
let l = 0;
|
||||||
|
let offset = -1;
|
||||||
|
let r = -1;
|
||||||
|
for (; (r = substr.indexOf("\n", r + 1)) !== -1; l++, offset = r)
|
||||||
|
;
|
||||||
|
offset += 1;
|
||||||
|
let ch = content.substr(offset, index - offset).length;
|
||||||
|
return { line: l, ch: ch };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function blank$1(text) {
|
||||||
|
return text === undefined || text === null || text === '';
|
||||||
|
}
|
||||||
|
function notBlank$1(text) {
|
||||||
|
return !blank$1(text);
|
||||||
|
}
|
||||||
|
function scrape(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
try {
|
||||||
|
const response = yield obsidian.requestUrl(url);
|
||||||
|
if (!response.headers['content-type'].includes('text/html'))
|
||||||
|
return getUrlFinalSegment$1(url);
|
||||||
|
const html = response.text;
|
||||||
|
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||||
|
const title = doc.querySelector('title');
|
||||||
|
if (blank$1(title === null || title === void 0 ? void 0 : title.innerText)) {
|
||||||
|
// If site is javascript based and has a no-title attribute when unloaded, use it.
|
||||||
|
var noTitle = title === null || title === void 0 ? void 0 : title.getAttr('no-title');
|
||||||
|
if (notBlank$1(noTitle)) {
|
||||||
|
return noTitle;
|
||||||
|
}
|
||||||
|
// Otherwise if the site has no title/requires javascript simply return Title Unknown
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
return title.innerText;
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
console.error(ex);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getUrlFinalSegment$1(url) {
|
||||||
|
try {
|
||||||
|
const segments = new URL(url).pathname.split('/');
|
||||||
|
const last = segments.pop() || segments.pop(); // Handle potential trailing slash
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
return 'File';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getPageTitle$1(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (!(url.startsWith('http') || url.startsWith('https'))) {
|
||||||
|
url = 'https://' + url;
|
||||||
|
}
|
||||||
|
return scrape(url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const electronPkg = require("electron");
|
||||||
|
function blank(text) {
|
||||||
|
return text === undefined || text === null || text === "";
|
||||||
|
}
|
||||||
|
function notBlank(text) {
|
||||||
|
return !blank(text);
|
||||||
|
}
|
||||||
|
// async wrapper to load a url and settle on load finish or fail
|
||||||
|
function load(window, url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
window.webContents.on("did-finish-load", (event) => resolve(event));
|
||||||
|
window.webContents.on("did-fail-load", (event) => reject(event));
|
||||||
|
window.loadURL(url);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function electronGetPageTitle(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const { remote } = electronPkg;
|
||||||
|
const { BrowserWindow } = remote;
|
||||||
|
try {
|
||||||
|
const window = new BrowserWindow({
|
||||||
|
width: 1000,
|
||||||
|
height: 600,
|
||||||
|
webPreferences: {
|
||||||
|
webSecurity: false,
|
||||||
|
nodeIntegration: true,
|
||||||
|
images: false,
|
||||||
|
},
|
||||||
|
show: false,
|
||||||
|
});
|
||||||
|
window.webContents.setAudioMuted(true);
|
||||||
|
window.webContents.on("will-navigate", (event, newUrl) => {
|
||||||
|
event.preventDefault();
|
||||||
|
window.loadURL(newUrl);
|
||||||
|
});
|
||||||
|
yield load(window, url);
|
||||||
|
try {
|
||||||
|
const title = window.webContents.getTitle();
|
||||||
|
window.destroy();
|
||||||
|
if (notBlank(title)) {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
window.destroy();
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
console.error(ex);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function nonElectronGetPageTitle(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
try {
|
||||||
|
const html = yield obsidian.request({ url });
|
||||||
|
const doc = new DOMParser().parseFromString(html, "text/html");
|
||||||
|
const title = doc.querySelectorAll("title")[0];
|
||||||
|
if (title == null || blank(title === null || title === void 0 ? void 0 : title.innerText)) {
|
||||||
|
// If site is javascript based and has a no-title attribute when unloaded, use it.
|
||||||
|
var noTitle = title === null || title === void 0 ? void 0 : title.getAttr("no-title");
|
||||||
|
if (notBlank(noTitle)) {
|
||||||
|
return noTitle;
|
||||||
|
}
|
||||||
|
// Otherwise if the site has no title/requires javascript simply return Title Unknown
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
return title.innerText;
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
console.error(ex);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getUrlFinalSegment(url) {
|
||||||
|
try {
|
||||||
|
const segments = new URL(url).pathname.split('/');
|
||||||
|
const last = segments.pop() || segments.pop(); // Handle potential trailing slash
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
return "File";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function tryGetFileType(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
try {
|
||||||
|
const response = yield fetch(url, { method: "HEAD" });
|
||||||
|
// Ensure site returns an ok status code before scraping
|
||||||
|
if (!response.ok) {
|
||||||
|
return "Site Unreachable";
|
||||||
|
}
|
||||||
|
// Ensure site is an actual HTML page and not a pdf or 3 gigabyte video file.
|
||||||
|
let contentType = response.headers.get("content-type");
|
||||||
|
if (!contentType.includes("text/html")) {
|
||||||
|
return getUrlFinalSegment(url);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getPageTitle(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
// If we're on Desktop use the Electron scraper
|
||||||
|
if (!(url.startsWith("http") || url.startsWith("https"))) {
|
||||||
|
url = "https://" + url;
|
||||||
|
}
|
||||||
|
// Try to do a HEAD request to see if the site is reachable and if it's an HTML page
|
||||||
|
// If we error out due to CORS, we'll just try to scrape the page anyway.
|
||||||
|
let fileType = yield tryGetFileType(url);
|
||||||
|
if (fileType) {
|
||||||
|
return fileType;
|
||||||
|
}
|
||||||
|
if (electronPkg != null) {
|
||||||
|
return electronGetPageTitle(url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nonElectronGetPageTitle(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class AutoLinkTitle extends obsidian.Plugin {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.shortTitle = (title) => {
|
||||||
|
if (this.settings.maximumTitleLength === 0) {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
if (title.length < this.settings.maximumTitleLength + 3) {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
const shortenedTitle = `${title.slice(0, this.settings.maximumTitleLength)}...`;
|
||||||
|
return shortenedTitle;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
onload() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
console.log("loading obsidian-auto-link-title");
|
||||||
|
yield this.loadSettings();
|
||||||
|
this.blacklist = this.settings.websiteBlacklist
|
||||||
|
.split(",")
|
||||||
|
.map((s) => s.trim())
|
||||||
|
.filter((s) => s.length > 0);
|
||||||
|
// Listen to paste event
|
||||||
|
this.pasteFunction = this.pasteUrlWithTitle.bind(this);
|
||||||
|
// Listen to drop event
|
||||||
|
this.dropFunction = this.dropUrlWithTitle.bind(this);
|
||||||
|
this.addCommand({
|
||||||
|
id: "auto-link-title-paste",
|
||||||
|
name: "Paste URL and auto fetch title",
|
||||||
|
editorCallback: (editor) => this.manualPasteUrlWithTitle(editor),
|
||||||
|
hotkeys: [],
|
||||||
|
});
|
||||||
|
this.addCommand({
|
||||||
|
id: "auto-link-title-normal-paste",
|
||||||
|
name: "Normal paste (no fetching behavior)",
|
||||||
|
editorCallback: (editor) => this.normalPaste(editor),
|
||||||
|
hotkeys: [
|
||||||
|
{
|
||||||
|
modifiers: ["Mod", "Shift"],
|
||||||
|
key: "v",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
this.registerEvent(this.app.workspace.on("editor-paste", this.pasteFunction));
|
||||||
|
this.registerEvent(this.app.workspace.on("editor-drop", this.dropFunction));
|
||||||
|
this.addCommand({
|
||||||
|
id: "enhance-url-with-title",
|
||||||
|
name: "Enhance existing URL with link and title",
|
||||||
|
editorCallback: (editor) => this.addTitleToLink(editor),
|
||||||
|
hotkeys: [
|
||||||
|
{
|
||||||
|
modifiers: ["Mod", "Shift"],
|
||||||
|
key: "e",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
this.addSettingTab(new AutoLinkTitleSettingTab(this.app, this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
addTitleToLink(editor) {
|
||||||
|
// Only attempt fetch if online
|
||||||
|
if (!navigator.onLine)
|
||||||
|
return;
|
||||||
|
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
||||||
|
// If the cursor is on a raw html link, convert to a markdown link and fetch title
|
||||||
|
if (CheckIf.isUrl(selectedText)) {
|
||||||
|
this.convertUrlToTitledLink(editor, selectedText);
|
||||||
|
}
|
||||||
|
// If the cursor is on the URL part of a markdown link, fetch title and replace existing link title
|
||||||
|
else if (CheckIf.isLinkedUrl(selectedText)) {
|
||||||
|
const link = this.getUrlFromLink(selectedText);
|
||||||
|
this.convertUrlToTitledLink(editor, link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
normalPaste(editor) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
let clipboardText = yield navigator.clipboard.readText();
|
||||||
|
if (clipboardText === null || clipboardText === "")
|
||||||
|
return;
|
||||||
|
editor.replaceSelection(clipboardText);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Simulate standard paste but using editor.replaceSelection with clipboard text since we can't seem to dispatch a paste event.
|
||||||
|
manualPasteUrlWithTitle(editor) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const clipboardText = yield navigator.clipboard.readText();
|
||||||
|
// Only attempt fetch if online
|
||||||
|
if (!navigator.onLine) {
|
||||||
|
editor.replaceSelection(clipboardText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (clipboardText == null || clipboardText == "")
|
||||||
|
return;
|
||||||
|
// If its not a URL, we return false to allow the default paste handler to take care of it.
|
||||||
|
// Similarly, image urls don't have a meaningful <title> attribute so downloading it
|
||||||
|
// to fetch the title is a waste of bandwidth.
|
||||||
|
if (!CheckIf.isUrl(clipboardText) || CheckIf.isImage(clipboardText)) {
|
||||||
|
editor.replaceSelection(clipboardText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If it looks like we're pasting the url into a markdown link already, don't fetch title
|
||||||
|
// as the user has already probably put a meaningful title, also it would lead to the title
|
||||||
|
// being inside the link.
|
||||||
|
if (CheckIf.isMarkdownLinkAlready(editor) || CheckIf.isAfterQuote(editor)) {
|
||||||
|
editor.replaceSelection(clipboardText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If url is pasted over selected text and setting is enabled, no need to fetch title,
|
||||||
|
// just insert a link
|
||||||
|
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
||||||
|
if (selectedText && this.settings.shouldPreserveSelectionAsTitle) {
|
||||||
|
editor.replaceSelection(`[${selectedText}](${clipboardText})`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// At this point we're just pasting a link in a normal fashion, fetch its title.
|
||||||
|
this.convertUrlToTitledLink(editor, clipboardText);
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pasteUrlWithTitle(clipboard, editor) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (!this.settings.enhanceDefaultPaste) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (clipboard.defaultPrevented)
|
||||||
|
return;
|
||||||
|
// Only attempt fetch if online
|
||||||
|
if (!navigator.onLine)
|
||||||
|
return;
|
||||||
|
let clipboardText = clipboard.clipboardData.getData("text/plain");
|
||||||
|
if (clipboardText === null || clipboardText === "")
|
||||||
|
return;
|
||||||
|
// If its not a URL, we return false to allow the default paste handler to take care of it.
|
||||||
|
// Similarly, image urls don't have a meaningful <title> attribute so downloading it
|
||||||
|
// to fetch the title is a waste of bandwidth.
|
||||||
|
if (!CheckIf.isUrl(clipboardText) || CheckIf.isImage(clipboardText)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// We've decided to handle the paste, stop propagation to the default handler.
|
||||||
|
clipboard.stopPropagation();
|
||||||
|
clipboard.preventDefault();
|
||||||
|
// If it looks like we're pasting the url into a markdown link already, don't fetch title
|
||||||
|
// as the user has already probably put a meaningful title, also it would lead to the title
|
||||||
|
// being inside the link.
|
||||||
|
if (CheckIf.isMarkdownLinkAlready(editor) || CheckIf.isAfterQuote(editor)) {
|
||||||
|
editor.replaceSelection(clipboardText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If url is pasted over selected text and setting is enabled, no need to fetch title,
|
||||||
|
// just insert a link
|
||||||
|
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
||||||
|
if (selectedText && this.settings.shouldPreserveSelectionAsTitle) {
|
||||||
|
editor.replaceSelection(`[${selectedText}](${clipboardText})`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// At this point we're just pasting a link in a normal fashion, fetch its title.
|
||||||
|
this.convertUrlToTitledLink(editor, clipboardText);
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
dropUrlWithTitle(dropEvent, editor) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (!this.settings.enhanceDropEvents) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dropEvent.defaultPrevented)
|
||||||
|
return;
|
||||||
|
// Only attempt fetch if online
|
||||||
|
if (!navigator.onLine)
|
||||||
|
return;
|
||||||
|
let dropText = dropEvent.dataTransfer.getData("text/plain");
|
||||||
|
if (dropText === null || dropText === "")
|
||||||
|
return;
|
||||||
|
// If its not a URL, we return false to allow the default paste handler to take care of it.
|
||||||
|
// Similarly, image urls don't have a meaningful <title> attribute so downloading it
|
||||||
|
// to fetch the title is a waste of bandwidth.
|
||||||
|
if (!CheckIf.isUrl(dropText) || CheckIf.isImage(dropText)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// We've decided to handle the paste, stop propagation to the default handler.
|
||||||
|
dropEvent.stopPropagation();
|
||||||
|
dropEvent.preventDefault();
|
||||||
|
// If it looks like we're pasting the url into a markdown link already, don't fetch title
|
||||||
|
// as the user has already probably put a meaningful title, also it would lead to the title
|
||||||
|
// being inside the link.
|
||||||
|
if (CheckIf.isMarkdownLinkAlready(editor) || CheckIf.isAfterQuote(editor)) {
|
||||||
|
editor.replaceSelection(dropText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If url is pasted over selected text and setting is enabled, no need to fetch title,
|
||||||
|
// just insert a link
|
||||||
|
let selectedText = (EditorExtensions.getSelectedText(editor) || "").trim();
|
||||||
|
if (selectedText && this.settings.shouldPreserveSelectionAsTitle) {
|
||||||
|
editor.replaceSelection(`[${selectedText}](${dropText})`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// At this point we're just pasting a link in a normal fashion, fetch its title.
|
||||||
|
this.convertUrlToTitledLink(editor, dropText);
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
isBlacklisted(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
yield this.loadSettings();
|
||||||
|
this.blacklist = this.settings.websiteBlacklist
|
||||||
|
.split(/,|\n/)
|
||||||
|
.map((s) => s.trim())
|
||||||
|
.filter((s) => s.length > 0);
|
||||||
|
return this.blacklist.some((site) => url.includes(site));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
convertUrlToTitledLink(editor, url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (yield this.isBlacklisted(url)) {
|
||||||
|
let domain = new URL(url).hostname;
|
||||||
|
editor.replaceSelection(`[${domain}](${url})`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Generate a unique id for find/replace operations for the title.
|
||||||
|
const pasteId = this.getPasteId();
|
||||||
|
// Instantly paste so you don't wonder if paste is broken
|
||||||
|
editor.replaceSelection(`[${pasteId}](${url})`);
|
||||||
|
// Fetch title from site, replace Fetching Title with actual title
|
||||||
|
const title = yield this.fetchUrlTitle(url);
|
||||||
|
const escapedTitle = this.escapeMarkdown(title);
|
||||||
|
const shortenedTitle = this.shortTitle(escapedTitle);
|
||||||
|
const text = editor.getValue();
|
||||||
|
const start = text.indexOf(pasteId);
|
||||||
|
if (start < 0) {
|
||||||
|
console.log(`Unable to find text "${pasteId}" in current editor, bailing out; link ${url}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const end = start + pasteId.length;
|
||||||
|
const startPos = EditorExtensions.getEditorPositionFromIndex(text, start);
|
||||||
|
const endPos = EditorExtensions.getEditorPositionFromIndex(text, end);
|
||||||
|
editor.replaceRange(shortenedTitle, startPos, endPos);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
escapeMarkdown(text) {
|
||||||
|
var unescaped = text.replace(/\\(\*|_|`|~|\\|\[|\])/g, "$1"); // unescape any "backslashed" character
|
||||||
|
var escaped = unescaped.replace(/(\*|_|`|<|>|~|\\|\[|\])/g, "\\$1"); // escape *, _, `, ~, \, [, ], <, and >
|
||||||
|
var escaped = unescaped.replace(/(\*|_|`|\||<|>|~|\\|\[|\])/g, "\\$1"); // escape *, _, `, ~, \, |, [, ], <, and >
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
fetchUrlTitleViaLinkPreview(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (this.settings.linkPreviewApiKey.length !== 32) {
|
||||||
|
console.error("LinkPreview API key is not 32 characters long, please check your settings");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const apiEndpoint = `https://api.linkpreview.net/?q=${encodeURIComponent(url)}`;
|
||||||
|
const response = yield fetch(apiEndpoint, {
|
||||||
|
headers: {
|
||||||
|
"X-Linkpreview-Api-Key": this.settings.linkPreviewApiKey,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const data = yield response.json();
|
||||||
|
return data.title;
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fetchUrlTitle(url) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
try {
|
||||||
|
let title = "";
|
||||||
|
title = yield this.fetchUrlTitleViaLinkPreview(url);
|
||||||
|
console.log(`Title via Link Preview: ${title}`);
|
||||||
|
if (title === "") {
|
||||||
|
console.log("Title via Link Preview failed, falling back to scraper");
|
||||||
|
if (this.settings.useNewScraper) {
|
||||||
|
console.log("Using new scraper");
|
||||||
|
title = yield getPageTitle$1(url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("Using old scraper");
|
||||||
|
title = yield getPageTitle(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(`Title: ${title}`);
|
||||||
|
title =
|
||||||
|
title.replace(/(\r\n|\n|\r)/gm, "").trim() ||
|
||||||
|
"Title Unavailable | Site Unreachable";
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return "Error fetching title";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getUrlFromLink(link) {
|
||||||
|
let urlRegex = new RegExp(DEFAULT_SETTINGS.linkRegex);
|
||||||
|
return urlRegex.exec(link)[2];
|
||||||
|
}
|
||||||
|
getPasteId() {
|
||||||
|
var base = "Fetching Title";
|
||||||
|
if (this.settings.useBetterPasteId) {
|
||||||
|
return this.getBetterPasteId(base);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return `${base}#${this.createBlockHash()}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getBetterPasteId(base) {
|
||||||
|
// After every character, add 0, 1 or 2 invisible characters
|
||||||
|
// so that to the user it looks just like the base string.
|
||||||
|
// The number of combinations is 3^14 = 4782969
|
||||||
|
let result = "";
|
||||||
|
var invisibleCharacter = "\u200B";
|
||||||
|
var maxInvisibleCharacters = 2;
|
||||||
|
for (var i = 0; i < base.length; i++) {
|
||||||
|
var count = Math.floor(Math.random() * (maxInvisibleCharacters + 1));
|
||||||
|
result += base.charAt(i) + invisibleCharacter.repeat(count);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// Custom hashid by @shabegom
|
||||||
|
createBlockHash() {
|
||||||
|
let result = "";
|
||||||
|
var characters = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
var charactersLength = characters.length;
|
||||||
|
for (var i = 0; i < 4; i++) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
onunload() {
|
||||||
|
console.log("unloading obsidian-auto-link-title");
|
||||||
|
}
|
||||||
|
loadSettings() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
saveSettings() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
yield this.saveData(this.settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AutoLinkTitle;
|
||||||
|
|
||||||
|
|
||||||
|
/* nosourcemap */
|
||||||
10
.obsidian/plugins/obsidian-auto-link-title/manifest.json
vendored
Normal file
10
.obsidian/plugins/obsidian-auto-link-title/manifest.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"id": "obsidian-auto-link-title",
|
||||||
|
"name": "Auto Link Title",
|
||||||
|
"version": "1.5.5",
|
||||||
|
"minAppVersion": "0.12.17",
|
||||||
|
"description": "This plugin automatically fetches the titles of links from the web",
|
||||||
|
"author": "Matt Furden",
|
||||||
|
"authorUrl": "https://github.com/zolrath",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
||||||
1
.obsidian/plugins/obsidian-auto-link-title/styles.css
vendored
Normal file
1
.obsidian/plugins/obsidian-auto-link-title/styles.css
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/* no styles */
|
||||||
2638
.obsidian/plugins/obsidian-link-embed/main.js
vendored
Normal file
2638
.obsidian/plugins/obsidian-link-embed/main.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10
.obsidian/plugins/obsidian-link-embed/manifest.json
vendored
Normal file
10
.obsidian/plugins/obsidian-link-embed/manifest.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"id": "obsidian-link-embed",
|
||||||
|
"name": "Link Embed",
|
||||||
|
"version": "2.9.2",
|
||||||
|
"minAppVersion": "0.12.0",
|
||||||
|
"description": "This plugin auto-fetches page metadata to embed Notion-style link preview cards.",
|
||||||
|
"author": "SErAphLi",
|
||||||
|
"authorUrl": "https://github.com/Seraphli",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
||||||
363
.obsidian/plugins/obsidian-link-embed/styles.css
vendored
Normal file
363
.obsidian/plugins/obsidian-link-embed/styles.css
vendored
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
.w {
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: none transparent;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.em > a,
|
||||||
|
.tc > a,
|
||||||
|
.th > a {
|
||||||
|
background-color: transparent;
|
||||||
|
-webkit-text-decoration-skip: objects;
|
||||||
|
}
|
||||||
|
.em > a,
|
||||||
|
.tc > a,
|
||||||
|
.th > a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
-ms-touch-action: manipulation;
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
.w {
|
||||||
|
line-height: 1.4;
|
||||||
|
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI',
|
||||||
|
Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: inherit;
|
||||||
|
-webkit-hyphens: auto;
|
||||||
|
-moz-hyphens: auto;
|
||||||
|
-ms-hyphens: auto;
|
||||||
|
hyphens: auto;
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
.t,
|
||||||
|
.w,
|
||||||
|
.wf {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@supports (-webkit-overflow-scrolling: touch) {
|
||||||
|
.w {
|
||||||
|
max-width: 100vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.wc,
|
||||||
|
.wt {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
._sm {
|
||||||
|
background: inherit;
|
||||||
|
}
|
||||||
|
._lc .wf {
|
||||||
|
-ms-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
._lc .wt {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.wt {
|
||||||
|
padding: 8px 10px;
|
||||||
|
}
|
||||||
|
@media (min-width: 360px) {
|
||||||
|
.wt {
|
||||||
|
padding: 12px 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 600px) {
|
||||||
|
.wt {
|
||||||
|
padding: 16px 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
._lc._sm:not(.xd) .wc {
|
||||||
|
min-width: 100px;
|
||||||
|
width: 100px;
|
||||||
|
min-height: 100px;
|
||||||
|
}
|
||||||
|
._lc._sm:not(.xd) .wc._wi {
|
||||||
|
max-width: min(50%, 200px);
|
||||||
|
}
|
||||||
|
@media (min-width: 360px) {
|
||||||
|
._lc._sm:not(.xd) .wc {
|
||||||
|
min-width: 110px;
|
||||||
|
width: 110px;
|
||||||
|
min-height: 110px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 360px) {
|
||||||
|
._lc._sm:not(.xd) .wc._wi {
|
||||||
|
max-width: min(50%, 220px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 460px) {
|
||||||
|
._lc._sm:not(.xd) .wc {
|
||||||
|
min-width: 140px;
|
||||||
|
width: 140px;
|
||||||
|
min-height: 140px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 460px) {
|
||||||
|
._lc._sm:not(.xd) .wc._wi {
|
||||||
|
max-width: min(50%, 280px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 600px) {
|
||||||
|
._lc._sm:not(.xd) .wc {
|
||||||
|
min-width: 160px;
|
||||||
|
width: 160px;
|
||||||
|
min-height: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 600px) {
|
||||||
|
._lc._sm:not(.xd) .wc._wi {
|
||||||
|
max-width: min(50%, 320px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@supports (-moz-appearance: meterbar) and (all: initial) {
|
||||||
|
._lc .wc {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
-ms-flex-align: stretch;
|
||||||
|
align-items: stretch;
|
||||||
|
-ms-flex-line-pack: stretch;
|
||||||
|
align-content: stretch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
._lc._ts .th {
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
}
|
||||||
|
._lc._ts._lh14 .th {
|
||||||
|
max-height: 1.4em;
|
||||||
|
}
|
||||||
|
._lc._ts .td {
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
}
|
||||||
|
._lc._ts._lh14 .td {
|
||||||
|
max-height: 2.8em;
|
||||||
|
}
|
||||||
|
@media (min-width: 460px) {
|
||||||
|
._lc._ts .th {
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
}
|
||||||
|
._lc._ts._lh14 .th {
|
||||||
|
max-height: 1.4em;
|
||||||
|
}
|
||||||
|
._lc._ts .td {
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
}
|
||||||
|
._lc._ts._lh14 .td {
|
||||||
|
max-height: 4.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.t {
|
||||||
|
-webkit-hyphens: auto;
|
||||||
|
-moz-hyphens: auto;
|
||||||
|
-ms-hyphens: auto;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
.td,
|
||||||
|
.th {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
@supports (display: -webkit-box) {
|
||||||
|
.td,
|
||||||
|
.th {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.td {
|
||||||
|
vertical-align: inherit;
|
||||||
|
}
|
||||||
|
.tf,
|
||||||
|
.th {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
.td {
|
||||||
|
margin-bottom: 0.6em;
|
||||||
|
}
|
||||||
|
._od .tf:last-child {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
.tf {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.tc {
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
@media (min-width: 460px) {
|
||||||
|
.td {
|
||||||
|
margin-bottom: 0.7em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
._ffsa {
|
||||||
|
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI',
|
||||||
|
Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
}
|
||||||
|
._fwn {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
._fwb {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
._fsn {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
._lh14 {
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
._f0,
|
||||||
|
._f1m {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
._f1p {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
@media (min-width: 360px) {
|
||||||
|
._f0 {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
._f1p {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 460px) {
|
||||||
|
._f1m {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
._f0 {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
._f1p {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 600px) {
|
||||||
|
._f1m {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
._f0 {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
._f1p {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.e {
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@supports (-moz-appearance: meterbar) and (all: initial) {
|
||||||
|
._lc .e {
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
._lc:not(._ap) .e {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.em {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.c {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.c {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: no-repeat center;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
.c {
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
.w {
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
.t {
|
||||||
|
line-height: 1.4;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
.th {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
.tf {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.tw {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.thl {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.embed {
|
||||||
|
border: 1px solid var(--background-modifier-border);
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: var(--radius-s);
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.06) 0px 1px 3px;
|
||||||
|
transition: border-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed:hover {
|
||||||
|
border-color: var(--background-modifier-border-hover);
|
||||||
|
}
|
||||||
|
.embed:focus {
|
||||||
|
border-color: var(--background-modifier-border-focus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embed buttons styling */
|
||||||
|
.embed-buttons {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
right: 5px;
|
||||||
|
z-index: 10;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button styling */
|
||||||
|
.refresh-button,
|
||||||
|
.copy-button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show buttons on hover over the embed element */
|
||||||
|
.embed:hover .embed-buttons {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Full opacity when hovering over the buttons */
|
||||||
|
.refresh-button:hover,
|
||||||
|
.copy-button:hover {
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"obsidian-prism-theme@@color-schemes-lt": "pt-color-scheme-periwinkle-lt",
|
"obsidian-prism-theme@@color-schemes-lt": "pt-color-scheme-periwinkle-lt",
|
||||||
"obsidian-prism-theme@@color-schemes-dt": "pt-color-scheme-custom-dt"
|
"obsidian-prism-theme@@color-schemes-dt": "pt-color-scheme-custom-dt",
|
||||||
|
"obsidian-prism-theme@@pt-titlebar-hide-text": false
|
||||||
}
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
{"月度/8月/8月.md":{"scroll":307.9525,"cursor":{"from":{"ch":0,"line":352},"to":{"ch":0,"line":352}}},"材料/服务器.md":{"scroll":10.7717,"cursor":{"from":{"ch":11,"line":27},"to":{"ch":11,"line":27}}},"月度/9月/9月.md":{"scroll":256.7974,"cursor":{"from":{"ch":0,"line":277},"to":{"ch":0,"line":277}}},"月度/7月/7月.md":{"scroll":138.3906,"cursor":{"from":{"ch":29,"line":147},"to":{"ch":29,"line":147}}},"月度/6月/6月.md":{"scroll":58.2917,"cursor":{"from":{"ch":72,"line":63},"to":{"ch":72,"line":63}}},"月度/5月/5月.md":{"scroll":93.1957,"cursor":{"from":{"ch":20,"line":105},"to":{"ch":20,"line":105}}},"月度/4月/4月.md":{"scroll":120.1806,"cursor":{"from":{"ch":20,"line":139},"to":{"ch":20,"line":139}}},"月度/3月/3月.md":{"scroll":32.7083,"cursor":{"from":{"ch":6,"line":39},"to":{"ch":6,"line":39}}},"月度/7月/7月工作总结及8月工作计划.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/6月/6月份晨午检bug修复.md":{"scroll":307.9981,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/7月/设备管理中心研发记录.md":{"scroll":110.1015,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/8月/CA身份认证app/CA身份认证app流程图.md":{"scroll":5.8654,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/9月/常见病/20250903常见病优化沟通.md":{"scroll":0.7205,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/9月/汇海/对接主机/不登录模式接口文档.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":12},"to":{"ch":0,"line":12}}},"月度/9月/汇海/对接主机/登录算法和密钥.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":9},"to":{"ch":0,"line":9}}},"月度/9月/汇海/对接主机/华夏汇海接口文档.md":{"scroll":230.5758,"cursor":{"from":{"ch":21,"line":248},"to":{"ch":21,"line":248}}}}
|
{"月度/8月/8月.md":{"scroll":307.9525,"cursor":{"from":{"ch":0,"line":352},"to":{"ch":0,"line":352}}},"材料/服务器.md":{"scroll":5.2801,"cursor":{"from":{"ch":0,"line":25},"to":{"ch":0,"line":25}}},"月度/9月/9月.md":{"scroll":197.2776,"cursor":{"from":{"ch":0,"line":214},"to":{"ch":0,"line":214}}},"月度/7月/7月.md":{"scroll":138.3906,"cursor":{"from":{"ch":29,"line":147},"to":{"ch":29,"line":147}}},"月度/6月/6月.md":{"scroll":58.2917,"cursor":{"from":{"ch":72,"line":63},"to":{"ch":72,"line":63}}},"月度/5月/5月.md":{"scroll":93.1957,"cursor":{"from":{"ch":20,"line":105},"to":{"ch":20,"line":105}}},"月度/4月/4月.md":{"scroll":120.1806,"cursor":{"from":{"ch":20,"line":139},"to":{"ch":20,"line":139}}},"月度/3月/3月.md":{"scroll":32.7083,"cursor":{"from":{"ch":6,"line":39},"to":{"ch":6,"line":39}}},"月度/7月/7月工作总结及8月工作计划.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/6月/6月份晨午检bug修复.md":{"scroll":307.9981,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/7月/设备管理中心研发记录.md":{"scroll":110.1015,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/8月/CA身份认证app/CA身份认证app流程图.md":{"scroll":5.8654,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/9月/常见病/20250903常见病优化沟通.md":{"scroll":0.7205,"cursor":{"from":{"ch":0,"line":0},"to":{"ch":0,"line":0}}},"月度/9月/汇海/对接主机/不登录模式接口文档.md":{"scroll":155.0112,"cursor":{"from":{"ch":3,"line":173},"to":{"ch":15,"line":173}}},"月度/9月/汇海/对接主机/登录算法和密钥.md":{"scroll":0,"cursor":{"from":{"ch":0,"line":9},"to":{"ch":0,"line":9}}},"月度/9月/汇海/对接主机/华夏汇海接口文档.md":{"scroll":1654.4332,"cursor":{"from":{"ch":19,"line":1328},"to":{"ch":19,"line":1328}}},"材料/配置/Obsidian快捷键.md":{"scroll":0,"cursor":{"from":{"ch":18,"line":16},"to":{"ch":18,"line":16}}},"材料/配置/工具.md":{"scroll":0,"cursor":{"from":{"ch":50,"line":0},"to":{"ch":50,"line":0}}}}
|
||||||
114
.obsidian/workspace.json
vendored
114
.obsidian/workspace.json
vendored
@@ -4,11 +4,11 @@
|
|||||||
"type": "split",
|
"type": "split",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "0fd9b856d0a70c15",
|
"id": "98d33b1dc65bb288",
|
||||||
"type": "tabs",
|
"type": "tabs",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "bd3868a8e5eaf912",
|
"id": "966d42c15131afc7",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "39126e2e94e3ddbf",
|
"id": "8fb520badf9154a8",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
@@ -34,37 +34,9 @@
|
|||||||
"icon": "lucide-file",
|
"icon": "lucide-file",
|
||||||
"title": "华夏汇海接口文档"
|
"title": "华夏汇海接口文档"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "fc808564fbb55487",
|
|
||||||
"type": "leaf",
|
|
||||||
"state": {
|
|
||||||
"type": "markdown",
|
|
||||||
"state": {
|
|
||||||
"file": "材料/服务器.md",
|
|
||||||
"mode": "source",
|
|
||||||
"source": false
|
|
||||||
},
|
|
||||||
"icon": "lucide-file",
|
|
||||||
"title": "服务器"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "b7629eda98506ca6",
|
|
||||||
"type": "leaf",
|
|
||||||
"state": {
|
|
||||||
"type": "markdown",
|
|
||||||
"state": {
|
|
||||||
"file": "月度/9月/9月.md",
|
|
||||||
"mode": "source",
|
|
||||||
"source": false
|
|
||||||
},
|
|
||||||
"icon": "lucide-file",
|
|
||||||
"title": "9月"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"currentTab": 3
|
"currentTab": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"direction": "vertical"
|
"direction": "vertical"
|
||||||
@@ -121,7 +93,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"direction": "horizontal",
|
"direction": "horizontal",
|
||||||
"width": 230.5
|
"width": 320.5110321044922
|
||||||
},
|
},
|
||||||
"right": {
|
"right": {
|
||||||
"id": "05ec8585e34884ac",
|
"id": "05ec8585e34884ac",
|
||||||
@@ -137,13 +109,13 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "outline",
|
"type": "outline",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "月度/9月/9月.md",
|
"file": "月度/9月/汇海/对接主机/华夏汇海接口文档.md",
|
||||||
"followCursor": false,
|
"followCursor": false,
|
||||||
"showSearch": false,
|
"showSearch": false,
|
||||||
"searchQuery": ""
|
"searchQuery": ""
|
||||||
},
|
},
|
||||||
"icon": "lucide-list",
|
"icon": "lucide-list",
|
||||||
"title": "9月 的大纲"
|
"title": "华夏汇海接口文档 的大纲"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -152,19 +124,53 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "outgoing-link",
|
"type": "outgoing-link",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "月度/9月/9月.md",
|
"file": "月度/9月/汇海/对接主机/华夏汇海接口文档.md",
|
||||||
"linksCollapsed": false,
|
"linksCollapsed": true,
|
||||||
"unlinkedCollapsed": true
|
"unlinkedCollapsed": true
|
||||||
},
|
},
|
||||||
"icon": "links-going-out",
|
"icon": "links-going-out",
|
||||||
"title": "9月 的出链列表"
|
"title": "华夏汇海接口文档 的出链列表"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "33286749d25422b3",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "backlink",
|
||||||
|
"state": {
|
||||||
|
"file": "月度/9月/汇海/对接主机/华夏汇海接口文档.md",
|
||||||
|
"collapseAll": false,
|
||||||
|
"extraContext": false,
|
||||||
|
"sortOrder": "alphabetical",
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": "",
|
||||||
|
"backlinkCollapsed": true,
|
||||||
|
"unlinkedCollapsed": false
|
||||||
|
},
|
||||||
|
"icon": "links-coming-in",
|
||||||
|
"title": "华夏汇海接口文档 的反向链接列表"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6e8e01b1cfdf9aba",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "tag",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "frequency",
|
||||||
|
"useHierarchy": true,
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
|
},
|
||||||
|
"icon": "lucide-tags",
|
||||||
|
"title": "标签"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"direction": "horizontal",
|
"direction": "horizontal",
|
||||||
"width": 224.5
|
"width": 251.5
|
||||||
},
|
},
|
||||||
"left-ribbon": {
|
"left-ribbon": {
|
||||||
"hiddenItems": {
|
"hiddenItems": {
|
||||||
@@ -182,26 +188,28 @@
|
|||||||
"obsidian-importer:Open Importer": false
|
"obsidian-importer:Open Importer": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"active": "696c93f3a8e665e1",
|
"active": "8fb520badf9154a8",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
"月度/9月/汇海/对接主机/华夏汇海接口文档.md",
|
|
||||||
"月度/9月/汇海/对接主机/不登录模式接口文档.md",
|
"月度/9月/汇海/对接主机/不登录模式接口文档.md",
|
||||||
|
"月度/9月/汇海/对接主机/华夏汇海接口文档.md",
|
||||||
|
"月度/9月/汇海/对接主机/~$登录模式API接口文档2.0 .docx",
|
||||||
"材料/服务器.md",
|
"材料/服务器.md",
|
||||||
"材料/frp/frpc.exe",
|
"材料/配置/工具.md",
|
||||||
"材料/frp/frpc.toml",
|
|
||||||
"材料/frp",
|
|
||||||
"月度/9月/9月.md",
|
"月度/9月/9月.md",
|
||||||
"月度/9月/漏扫/Alibaba druid index,html 未授权访问漏洞修复记录.docx",
|
"主机登录模式API接口文档 .docx.md",
|
||||||
"月度/Alibaba druid index,html 未授权访问漏洞修复记录.docx",
|
"材料/配置/文字内联短横线生成器.html",
|
||||||
"月度/9月/汇海/对接主机/2.0/主机登录模式API接口文档2.0 ~E0DB2.tmp",
|
"材料/配置/Obsidian快捷键.md",
|
||||||
|
"材料/配置/自定义短横线.html",
|
||||||
|
"材料/配置/新建 文本文档.html",
|
||||||
|
"材料/配置/新建 文本文档.txt",
|
||||||
|
"月度/月度封面.base",
|
||||||
|
"材料/frp/frpc_script.toml",
|
||||||
|
"材料/frp/新建 文本文档.toml",
|
||||||
|
"材料/frp/新建 文本文档.tom",
|
||||||
|
"材料/frp/新建 文本文档.txt",
|
||||||
"月度/9月/汇海/对接主机/2.0/人脸特征值下载.md",
|
"月度/9月/汇海/对接主机/2.0/人脸特征值下载.md",
|
||||||
"月度/9月/汇海/对接主机/登录算法和密钥.md",
|
"月度/9月/汇海/对接主机/登录算法和密钥.md",
|
||||||
"月度/9月/汇海/对接主机/2.0/~$登录模式API接口文档2.0 .docx",
|
|
||||||
"月度/9月/汇海/对接主机/2.0/主机登录模式API接口文档2.0 ~4FCCA.tmp",
|
|
||||||
"月度/9月/漏扫/~$6天衡QWSY渗透测试报告.docx",
|
|
||||||
"月度/9月/漏扫/9.6天衡QWSY渗透测试报告.docx",
|
|
||||||
"月度/8月/8月.md",
|
"月度/8月/8月.md",
|
||||||
"材料/配置/自定义短横线.md",
|
|
||||||
"月度/9月/调查问卷.md",
|
"月度/9月/调查问卷.md",
|
||||||
"月度/9月/石榴籽-家校通/家校通需求.md",
|
"月度/9月/石榴籽-家校通/家校通需求.md",
|
||||||
"月度/3月/3月.md",
|
"月度/3月/3月.md",
|
||||||
@@ -217,8 +225,6 @@
|
|||||||
"月度/9月/体质测试数据上传接口文档.md",
|
"月度/9月/体质测试数据上传接口文档.md",
|
||||||
"月度/9月/9.12与华夏汇海对接线上技术会.md",
|
"月度/9月/9.12与华夏汇海对接线上技术会.md",
|
||||||
"月度/9月/华夏汇海技术对接交流会议纪要.md",
|
"月度/9月/华夏汇海技术对接交流会议纪要.md",
|
||||||
"月度/9月/20250903常见病优化沟通.md",
|
|
||||||
"月度/8月/CA身份认证app/CA身份认证app流程图.md",
|
|
||||||
"图片/9月.png",
|
"图片/9月.png",
|
||||||
"月度/未命名.canvas",
|
"月度/未命名.canvas",
|
||||||
"图片/8月.png",
|
"图片/8月.png",
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ MaterialApp(
|
|||||||
[[解析汇海设备请求]]
|
[[解析汇海设备请求]]
|
||||||
[[不登录模式接口文档]]
|
[[不登录模式接口文档]]
|
||||||
[[登录算法和密钥]]
|
[[登录算法和密钥]]
|
||||||
[[主机登录模式API接口文档 .docx]]
|
|
||||||
|
|
||||||
3.高博士与技术部会议
|
3.高博士与技术部会议
|
||||||
<span style="color:#ffc000 !important;">石榴籽具体落实</span>
|
<span style="color:#ffc000 !important;">石榴籽具体落实</span>
|
||||||
@@ -275,3 +275,5 @@ http://47.109.23.162:8088/hhcrm/api/hhdevices/getbysn?sn=00%3A60%3A6e%3Ad4%3Ac6%
|
|||||||
1.<span style="color:#3EC1D3 !important;">对接汇海设备</span>将人脸逻辑写入wechat中,完善获取特征值的方法
|
1.<span style="color:#3EC1D3 !important;">对接汇海设备</span>将人脸逻辑写入wechat中,完善获取特征值的方法
|
||||||
2.<span style="color:#3EC1D3 !important;">常见病app</span> 增加批量上传
|
2.<span style="color:#3EC1D3 !important;">常见病app</span> 增加批量上传
|
||||||
|
|
||||||
|
|
||||||
|
# 9.19
|
||||||
|
|||||||
BIN
月度/9月/汇海/对接主机/~$登录模式API接口文档2.0 .docx
Normal file
BIN
月度/9月/汇海/对接主机/~$登录模式API接口文档2.0 .docx
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
材料/frp/frpc.exe
BIN
材料/frp/frpc.exe
Binary file not shown.
@@ -20,4 +20,4 @@ remotePort = 8081 # 服务器映射端口
|
|||||||
# type = "tcp"
|
# type = "tcp"
|
||||||
# localIP = "192.168.2.84"
|
# localIP = "192.168.2.84"
|
||||||
# localPort = 8082 # 另一个本地服务端口
|
# localPort = 8082 # 另一个本地服务端口
|
||||||
# remotePort = 8088 # 另一个服务器映射端口
|
# remotePort = 8088 # 另一个服务器映射端口
|
||||||
|
|||||||
13
材料/frp/frpc_script.toml
Normal file
13
材料/frp/frpc_script.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
serverAddr = "47.109.23.162"
|
||||||
|
serverPort = 7000
|
||||||
|
|
||||||
|
auth.method = "token"
|
||||||
|
auth.token = "token123456"
|
||||||
|
|
||||||
|
|
||||||
|
[[proxies]]
|
||||||
|
name = "web-tcp"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 802
|
||||||
|
remotePort = 8081
|
||||||
@@ -24,9 +24,6 @@ gitea数据库 gitea_binghuai
|
|||||||
## Frp
|
## Frp
|
||||||
http://frps.binghuai.xyz:[端口号]/
|
http://frps.binghuai.xyz:[端口号]/
|
||||||
|
|
||||||
CSjyj00
|
|
||||||
Tzcs!!!2024
|
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| ------------ | ------------ |
|
| ------------ | ------------ |
|
||||||
| 服务端口 | 7000 |
|
| 服务端口 | 7000 |
|
||||||
|
|||||||
9
材料/配置/工具.md
Normal file
9
材料/配置/工具.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
```embed
|
||||||
|
title: "lpane"
|
||||||
|
image: "http://lpane.binghuai.xyz/public/favicon.png"
|
||||||
|
description: ""
|
||||||
|
url: "http://lpane.binghuai.xyz/a70aef6b25"
|
||||||
|
favicon: ""
|
||||||
|
```
|
||||||
|
|
||||||
|
[文字内联短横线生成器](https://www.binghuai.xyz/markdown/20250919135850178.html)
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user