Skip to content
This repository has been archived by the owner on Aug 27, 2023. It is now read-only.

Commit

Permalink
Major update. See release 0.2.0 for changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
nothingislost committed Oct 4, 2021
1 parent 378ff36 commit d723b61
Show file tree
Hide file tree
Showing 16 changed files with 2,002 additions and 251 deletions.
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,41 @@ This setting is a fallback option if you do not want to inject CM into preview m

## Changelog

### 0.2.0

- This is a major release which adds/changes quite a few things
- **Updated:** Hide Markdown Tokens
- Further stabilization improvements
- Removed all usage of `display: none` in edit mode due to the fact that this hiding method breaks cursor placement
- All token hiding should be done with `font-family: monospace;font-size: 1px !important; letter-spacing: -1ch;color: transparent;`
- If you have a theme or CSS snippet that is using `display:none` on elements inside of a CodeMirror block, it is advised to disable those styles in favor of the token hiding provided by this plugin.
- Added the ability to enable/disable each token type individually
- Added hiding support for additional token types
- Highlight/Mark
- Internal link URL & Ref
- **New:** Container Attributes
- This new option applies data attributes to all CodeMirror line divs that describe the child elements contained within the line
- Think of this like Contextual Typography for Edit Mode
- This option currently applies the following attributes to each CodeMirror line
- [data-tag-name="<html_element_type>"]
- Currently supported HTML tags: ol, ul, h1-h6, code, frontmatter
- [data-heading="<the_full_text_of_any_heading_found>"]
- [data-hashtags="<space_delimited_list_of_all_tags_found>"]
- **New:** OpenMD Mode
- This new option replaces Obsidian's HyperMD mode with a modified version which enables new functionality
- The new mode is forked from [official HyperMD mode](https://github.com/laobubu/HyperMD/blob/master/src/mode/hypermd.ts) and tries to replicate any Obsidian specific customizations
- **Warning:** This new mode could have missing features or differences in parsing behavior when compared to the default Obsidian mode. Please raise an issue for any regressions or bugs encountered.
- New functionality provided by this mode:
- Enhanced parsing of internal links to split up file name, reference, and alias into distinct spans. This allows for proper hiding of internal link tokens when using the "Hide Markdown Tokens" feature
- Fixed the handling of hashtags that include underscores
- **New:** Collapse External Links
- This features collapses external links (in edit mode) so that they only show the link name. The full link text will expand when clicking into the link.
- **Updated:** Edit Mode Click Handler
- This option has been updated to add a class to the div.cm-s-obsidian element whenever a modifier key is pressed
- Currently supports ctrl (.HyperMD-with-ctrl), alt (.HyperMD-with-alt), meta (.HyperMD-with-meta)
- This feature allows you to apply conditional CSS like changing the cursor to a pointer when hovering a link and also pressing ctrl/cmd
- **New:** Set cursor blink rate

### 0.1.4

- Fixed a bug which would cause "can't read property 'length' of undefined" randomly, when opening files
Expand All @@ -138,7 +173,6 @@ This setting is a fallback option if you do not want to inject CM into preview m
- Stabilize Hide Markdown Tokens
- The cursor placement logic has been replaced with a hopefully more stable method which prevents the scroll position from jumping up and down on click
- The only outstanding cursor bug that I'm aware of is when placing the cursor to the right of the fold widget on a folded line
-

### 0.1.3

Expand Down
9 changes: 9 additions & 0 deletions manifest-beta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"id": "obsidian-codemirror-options",
"name": "CodeMirror Options",
"version": "0.2.0",
"description": "Customize the functionality and appearance of Obsidian's edit mode",
"author": "NothingIsLost",
"authorUrl": "https://github.com/nothingislost",
"isDesktopOnly": true
}
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"name": "obsidian-codemirror-options",
"version": "0.1.4",
"description": "Enable/Disable certain CodeMirror options",
"version": "0.2.0",
"description": "Customize the functionality of Obsidian's edit mode",
"main": "main.js",
"scripts": {
"dev": "rollup --config rollup.config.js -w",
"build": "rollup --config rollup.config.js",
"build": "rollup --config rollup.config.js --environment BUILD:production",
"lint": "eslint . --ext .ts"
},
"keywords": [],
"author": "",
"author": "NothingIslost <[@nothingislost](https://github.com/nothingislost)>",
"license": "MIT",
"devDependencies": {
"@giotramu/prettier-config": "^1.1.2",
Expand All @@ -20,7 +20,6 @@
"@typescript-eslint/eslint-plugin": "^4.29.3",
"@typescript-eslint/parser": "^4.29.3",
"@rollup/plugin-json": "^4.1.0",
"@0xgg/echomd": "^1.0.4",
"codemirror": "^5.62.2",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1",
Expand Down
25 changes: 21 additions & 4 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,42 @@ import typescript from '@rollup/plugin-typescript';
import {nodeResolve} from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import copy from 'rollup-plugin-copy';
import postcss from 'rollup-plugin-postcss'
import json from "@rollup/plugin-json";

const isProd = (process.env.BUILD === 'production');

const banner =
`/*
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository
*/
`;

export default {
input: './src/main.ts',
output: {
dir: './dist/',
sourcemap: 'inline',
sourcemapExcludeSources: isProd,
format: 'cjs',
exports: 'default'
exports: 'default',
banner,
},
external: ['obsidian'],
plugins: [
typescript(),
nodeResolve({browser: true, preferBuiltins: true}),
commonjs(),
json(),
postcss({
plugins: []
}),
copy({
targets: [
{ src: 'manifest.json', dest: './dist/' },
{ src: 'styles.css', dest: './dist/' }
], flatten: true
{ src: './manifest.json', dest: './dist/' },
{ src: './styles.css', dest: './dist/' }
], flatten: false
})
]
};
104 changes: 104 additions & 0 deletions src/container-attributes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
export function onRenderLine(cm: CodeMirror.Editor, line: CodeMirror.LineHandle, el: HTMLElement) {
// setTimeout here since the renderLine event is emitted before the element is added to the DOM
// if we don't wait, we won't know who our parent is
const parentElement = el.parentElement;
if (!parentElement)
el.addEventListener("DOMNodeInserted", (event: MutationEvent) => procLine(cm, line, el, (event.relatedNode as HTMLElement)), { once: true });
// we can't do anything with a parentless element
}

function procLine(cm: CodeMirror.Editor, line: CodeMirror.LineHandle, el: HTMLElement, parentEl: HTMLElement) {
// for some reason, codemirror or hmd skips putting elements in a wrapping div
// unsure what causes this to happen but try and account for it by falling back
// if the parent is the root codemirror-code element
if (parentEl.className === "CodeMirror-code") parentEl = el;

// clear existing data keys
clearDataKeys(parentEl.dataset);

// split child classes
const childClasses = line.styleClasses?.textClass?.split(" ");

// line.styles is an array of multi-class strings
// we combine all of the styles into a single string and then dedupe it
const childElementClasses = line.styles
?.filter((style: string | number) => typeof style === "string")
.join(" ")
.split(" ")
.filter((v, i, a) => a.indexOf(v) === i);

// look for anything labeled as a header
// extract its full text value (minus the initial hash)
if (childClasses?.includes("HyperMD-header")) {
parentEl.dataset["heading"] = line.text.match(/^[#]+[\s]+(.+)/)[1].trim();
}

// check line for any hashtags and add them to a new data key
const tokens = cm.getLineTokens(line.lineNo());
const parsedTokens = parseLineTokens(tokens);
if (parsedTokens) parentEl.dataset["hashtags"] = parseLineTokens(tokens);

// infer html tag type based on style classes
const htmlTag = childElementClasses ? lookupTag(childElementClasses) : null;
if (htmlTag) {
parentEl.dataset["tagName"] = htmlTag;
}
}

function clearDataKeys(keys: DOMStringMap) {
if (keys) {
Object.keys(keys).forEach(dataKey => {
delete keys[dataKey];
});
}
}

function parseLineTokens(tokens: any[]) {
tokens = tokens.filter((token: { type: string | string[] }) => token.type?.includes("hashtag-end"));
if (tokens.length) {
const hashtags = tokens.map((token: { string: any }) => token.string).join(" ");
if (hashtags.length) {
return tokens.map((token: { string: any }) => token.string).join(" ");
}
}
}

function lookupTag(classes: string[]) {
let htmlTag: string;
for (const className of classes) {
switch (className) {
case "formatting-list-ol":
htmlTag = "ol";
break;
case "formatting-list-ul":
htmlTag = "ul";
break;
case "header-1":
htmlTag = "h1";
break;
case "header-2":
htmlTag = "h2";
break;
case "header-3":
htmlTag = "h3";
break;
case "header-4":
htmlTag = "h4";
break;
case "header-5":
htmlTag = "h5";
break;
case "header-6":
htmlTag = "h6";
break;
case "hmd-codeblock":
htmlTag = "code";
break;
case "hmd-frontmatter":
htmlTag = "frontmatter";
break;
}
}
return htmlTag;
}

11 changes: 8 additions & 3 deletions src/hmd-click.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ var __importStar =

(function (mod) {
//[HyperMD] UMD patched!
/*plain env*/ mod(null, (HyperMD.Click = HyperMD.Click || {}), CodeMirror, HyperMD, HyperMD.ReadLink);
})(function (require, exports, CodeMirror, core_1, read_link_1) {
/*plain env*/ mod(null, (HyperMD.Click = HyperMD.Click || {}), CodeMirror, HyperMD);
})(function (require, exports, CodeMirror, core_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAddon =
Expand Down Expand Up @@ -108,6 +108,7 @@ var __importStar =
var el = _this.el;
var className = el.className,
newClassName = className;
var metaClass = "HyperMD-with-meta";
var altClass = "HyperMD-with-alt";
var ctrlClass = "HyperMD-with-ctrl";
if (!ev.altKey && className.indexOf(altClass) >= 0) {
Expand All @@ -116,7 +117,10 @@ var __importStar =
if (!ev.ctrlKey && className.indexOf(ctrlClass) >= 0) {
newClassName = className.replace(ctrlClass, "");
}
if (!ev.altKey && !ev.ctrlKey) {
if (!ev.metaKey && className.indexOf(metaClass) >= 0) {
newClassName = className.replace(metaClass, "");
}
if (!ev.altKey && !ev.ctrlKey && !ev.metaKey) {
_this._KeyDetectorActive = false;
el.removeEventListener("mousemove", _this._mouseMove_keyDetect, false);
}
Expand All @@ -126,6 +130,7 @@ var __importStar =
this._keyDown = function (ev) {
var kc = ev.keyCode || ev.which;
var className = "";
if (kc == 91 || kc == 92 || kc == 224) className = "HyperMD-with-meta";
if (kc == 17) className = "HyperMD-with-ctrl";
if (kc == 18) className = "HyperMD-with-alt";
var el = _this.el;
Expand Down
31 changes: 24 additions & 7 deletions src/hmd-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,7 @@
var prevState = prevToken ? prevToken.state : {};
var state = token.state;
var styles = " " + token.type + " ";

var ans = {
// em
em: state.em ? 1 /* IS_THIS_TYPE */ : prevState.em ? 2 /* LEAVING_THIS_TYPE */ : 0 /* NOTHING */,
Expand All @@ -948,7 +949,14 @@
// strong
strong: state.strong ? 1 /* IS_THIS_TYPE */ : prevState.strong ? 2 /* LEAVING_THIS_TYPE */ : 0 /* NOTHING */,
// mark
mark: state.mark ? 1 /* IS_THIS_TYPE */ : prevState.mark ? 2 /* LEAVING_THIS_TYPE */ : 0 /* NOTHING */,
// mark: state.mark ? 1 /* IS_THIS_TYPE */ : prevState.mark ? 2 /* LEAVING_THIS_TYPE */ : 0 /* NOTHING */,
mark:
(token && token.type?.includes("formatting-highlight") && token.string === "==" && (!prevToken || (prevToken && prevToken.type !== "highlight")) ||
(token && token.type === "highlight"))
? 1
: token && token.type && token.type?.includes("formatting-highlight") && token.string === "==" && prevToken && prevToken.type === "highlight"
? 2
: 0,
// ins
ins: state.ins ? 1 /* IS_THIS_TYPE */ : prevState.ins ? 2 /* LEAVING_THIS_TYPE */ : 0 /* NOTHING */,
// sub
Expand All @@ -957,6 +965,14 @@
sup: state.sup ? 1 /* IS_THIS_TYPE */ : prevState.sup ? 2 /* LEAVING_THIS_TYPE */ : 0 /* NOTHING */,
// code
code: state.code ? 1 /* IS_THIS_TYPE */ : prevState.code ? 2 /* LEAVING_THIS_TYPE */ : 0 /* NOTHING */,
// obsidian internal link
internalLink:
(token && token.type === "formatting-link" && token.string === "[[") ||
(token && token.type === "hmd-internal-link")
? 1
: token && token.type && token.type === "formatting-link" && token.string === "]]"
? 2
: 0,
// linkText
linkText: state.linkText
? state.hmdLinkType === 3 /* NORMAL */ ||
Expand Down Expand Up @@ -986,6 +1002,7 @@
? 2 /* LEAVING_THIS_TYPE */
: 0 /* NOTHING */,
};
ans["highlight"] = ans["mark"] // create a token alias
return ans;
};
/** get spans from a line and update the cache */
Expand Down Expand Up @@ -1091,15 +1108,15 @@

function updateCursorDisplay(cm, skipCacheCleaning) {
if (!skipCacheCleaning) {
var lvs = cm.display.view // LineView s
var lvs = cm.display.view; // LineView s
for (var lineView of lvs) {
if (lineView.measure) lineView.measure.cache = {}
if (lineView.measure) lineView.measure.cache = {};
}
}

setTimeout(function () {
cm.display.input.showSelection(cm.display.input.prepareSelection())
}, 60) // wait for css style
cm.display.input.showSelection(cm.display.input.prepareSelection());
}, 60); // wait for css style
}

/**
Expand Down Expand Up @@ -1153,7 +1170,7 @@
exports.cm_internal = cm_internal;
exports.contains = contains;
exports.debounce = debounce;
exports.updateCursorDisplay = updateCursorDisplay
exports.updateCursorDisplay = updateCursorDisplay;
exports.expandRange = expandRange;
exports.fromTextArea = fromTextArea;
exports.getEveryCharToken = getEveryCharToken;
Expand Down
Loading

0 comments on commit d723b61

Please sign in to comment.