mirror of
https://github.com/marktext/marktext.git
synced 2025-05-02 11:20:25 +08:00
feat: support solidity in codeblock and optimization of file icons (#2775)
* feat: support solidity in codeblock and optimization of file icons * feat: update file icons
This commit is contained in:
parent
c6d4368988
commit
8af9605e35
@ -36,6 +36,7 @@
|
|||||||
"@electron/remote": "^2.0.1",
|
"@electron/remote": "^2.0.1",
|
||||||
"@hfelix/electron-localshortcut": "^3.1.1",
|
"@hfelix/electron-localshortcut": "^3.1.1",
|
||||||
"@hfelix/electron-spellchecker": "^2.0.0",
|
"@hfelix/electron-spellchecker": "^2.0.0",
|
||||||
|
"@marktext/file-icons": "^1.0.4",
|
||||||
"@octokit/rest": "^18.12.0",
|
"@octokit/rest": "^18.12.0",
|
||||||
"arg": "^5.0.1",
|
"arg": "^5.0.1",
|
||||||
"axios": "0.22.0",
|
"axios": "0.22.0",
|
||||||
@ -54,7 +55,6 @@
|
|||||||
"element-resize-detector": "^1.2.4",
|
"element-resize-detector": "^1.2.4",
|
||||||
"element-ui": "^2.15.7",
|
"element-ui": "^2.15.7",
|
||||||
"execall": "^2.0.0",
|
"execall": "^2.0.0",
|
||||||
"file-icons-js": "1.0.3",
|
|
||||||
"flowchart.js": "^1.17.0",
|
"flowchart.js": "^1.17.0",
|
||||||
"fontmanager-redux": "^1.1.0",
|
"fontmanager-redux": "^1.1.0",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
import katex from 'katex'
|
import katex from 'katex'
|
||||||
|
import prism, { loadedLanguages, transfromAliasToOrigin } from '../../../prism/'
|
||||||
import 'katex/dist/contrib/mhchem.min.js'
|
import 'katex/dist/contrib/mhchem.min.js'
|
||||||
import prism, { loadedCache, transfromAliasToOrigin } from '../../../prism/'
|
|
||||||
import { CLASS_OR_ID, DEVICE_MEMORY, PREVIEW_DOMPURIFY_CONFIG, HAS_TEXT_BLOCK_REG } from '../../../config'
|
import { CLASS_OR_ID, DEVICE_MEMORY, PREVIEW_DOMPURIFY_CONFIG, HAS_TEXT_BLOCK_REG } from '../../../config'
|
||||||
import { tokenizer } from '../../'
|
import { tokenizer } from '../../'
|
||||||
import { snakeToCamel, sanitize, escapeHtml, getLongUniqueId, getImageInfo } from '../../../utils'
|
import { snakeToCamel, sanitize, escapeHtml, getLongUniqueId, getImageInfo } from '../../../utils'
|
||||||
@ -234,7 +234,7 @@ export default function renderLeafBlock (parent, block, activeBlocks, matches, u
|
|||||||
|
|
||||||
// transfrom alias to original language
|
// transfrom alias to original language
|
||||||
const transformedLang = transfromAliasToOrigin([lang])[0]
|
const transformedLang = transfromAliasToOrigin([lang])[0]
|
||||||
if (transformedLang && /\S/.test(code) && loadedCache.has(transformedLang)) {
|
if (transformedLang && /\S/.test(code) && loadedLanguages.has(transformedLang)) {
|
||||||
const wrapper = document.createElement('div')
|
const wrapper = document.createElement('div')
|
||||||
wrapper.classList.add(`language-${transformedLang}`)
|
wrapper.classList.add(`language-${transformedLang}`)
|
||||||
wrapper.innerHTML = code
|
wrapper.innerHTML = code
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Prism from 'prismjs'
|
import Prism from 'prismjs'
|
||||||
import { filter } from 'fuzzaldrin'
|
import { filter } from 'fuzzaldrin'
|
||||||
import initLoadLanguage, { loadedCache, transfromAliasToOrigin } from './loadLanguage'
|
import initLoadLanguage, { loadedLanguages, transfromAliasToOrigin } from './loadLanguage'
|
||||||
import languages from './languages'
|
import { languages } from 'prismjs/components.js'
|
||||||
|
|
||||||
const prism = Prism
|
const prism = Prism
|
||||||
window.Prism = Prism
|
window.Prism = Prism
|
||||||
@ -44,9 +44,8 @@ loadLanguage('yaml')
|
|||||||
export {
|
export {
|
||||||
search,
|
search,
|
||||||
loadLanguage,
|
loadLanguage,
|
||||||
loadedCache,
|
loadedLanguages,
|
||||||
transfromAliasToOrigin,
|
transfromAliasToOrigin
|
||||||
languages
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default prism
|
export default prism
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,41 +1,19 @@
|
|||||||
import languages from './languages'
|
import components from 'prismjs/components.js'
|
||||||
let peerDependentsMap = null
|
import getLoader from 'prismjs/dependencies'
|
||||||
export const loadedCache = new Set(['markup', 'css', 'clike', 'javascript'])
|
import { getDefer } from '../utils'
|
||||||
const prismComponentCache = new Map()
|
/**
|
||||||
|
* The set of all languages which have been loaded using the below function.
|
||||||
|
*
|
||||||
|
* @type {Set<string>}
|
||||||
|
*/
|
||||||
|
export const loadedLanguages = new Set(['markup', 'css', 'clike', 'javascript'])
|
||||||
|
|
||||||
function getPeerDependentsMap () {
|
const { languages } = components
|
||||||
const peerDependentsMap = {}
|
|
||||||
Object.keys(languages).forEach(function (language) {
|
|
||||||
if (language === 'meta') {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (languages[language].peerDependencies) {
|
|
||||||
let peerDependencies = languages[language].peerDependencies
|
|
||||||
if (!Array.isArray(peerDependencies)) {
|
|
||||||
peerDependencies = [peerDependencies]
|
|
||||||
}
|
|
||||||
peerDependencies.forEach(function (peerDependency) {
|
|
||||||
if (!peerDependentsMap[peerDependency]) {
|
|
||||||
peerDependentsMap[peerDependency] = []
|
|
||||||
}
|
|
||||||
peerDependentsMap[peerDependency].push(language)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return peerDependentsMap
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPeerDependents (mainLanguage) {
|
|
||||||
if (!peerDependentsMap) {
|
|
||||||
peerDependentsMap = getPeerDependentsMap()
|
|
||||||
}
|
|
||||||
return peerDependentsMap[mainLanguage] || []
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for the origin languge by alias
|
// Look for the origin languge by alias
|
||||||
export const transfromAliasToOrigin = arr => {
|
export const transfromAliasToOrigin = langs => {
|
||||||
const result = []
|
const result = []
|
||||||
for (const lang of arr) {
|
for (const lang of langs) {
|
||||||
if (languages[lang]) {
|
if (languages[lang]) {
|
||||||
result.push(lang)
|
result.push(lang)
|
||||||
} else {
|
} else {
|
||||||
@ -59,76 +37,47 @@ export const transfromAliasToOrigin = arr => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initLoadLanguage (Prism) {
|
function initLoadLanguage (Prism) {
|
||||||
return async function loadLanguages (arr, withoutDependencies) {
|
return async function loadLanguages (langs) {
|
||||||
// If no argument is passed, load all components
|
// If no argument is passed, load all components
|
||||||
if (!arr) {
|
if (!langs) {
|
||||||
arr = Object.keys(languages).filter(function (language) {
|
langs = Object.keys(languages).filter(function (lang) {
|
||||||
return language !== 'meta'
|
return lang !== 'meta'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (arr && !arr.length) {
|
|
||||||
|
if (langs && !langs.length) {
|
||||||
return Promise.reject(new Error('The first parameter should be a list of load languages or single language.'))
|
return Promise.reject(new Error('The first parameter should be a list of load languages or single language.'))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Array.isArray(arr)) {
|
if (!Array.isArray(langs)) {
|
||||||
arr = [arr]
|
langs = [langs]
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = []
|
const promises = []
|
||||||
const transformedLangs = transfromAliasToOrigin(arr)
|
// the user might have loaded languages via some other way or used `prism.js` which already includes some
|
||||||
for (const language of transformedLangs) {
|
// we don't need to validate the ids because `getLoader` will ignore invalid ones
|
||||||
// handle not existed
|
const loaded = [...loadedLanguages, ...Object.keys(Prism.languages)]
|
||||||
if (!languages[language]) {
|
|
||||||
promises.push(Promise.resolve({
|
getLoader(components, langs, loaded).load(async lang => {
|
||||||
lang: language,
|
const defer = getDefer()
|
||||||
|
promises.push(defer.promise)
|
||||||
|
if (!(lang in components.languages)) {
|
||||||
|
defer.resolve({
|
||||||
|
lang,
|
||||||
status: 'noexist'
|
status: 'noexist'
|
||||||
}))
|
})
|
||||||
continue
|
return
|
||||||
}
|
|
||||||
// handle already cached
|
|
||||||
if (loadedCache.has(language)) {
|
|
||||||
promises.push(Promise.resolve({
|
|
||||||
lang: language,
|
|
||||||
status: 'cached'
|
|
||||||
}))
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load dependencies first
|
delete Prism.languages[lang]
|
||||||
if (!withoutDependencies && languages[language].require) {
|
|
||||||
const results = await loadLanguages(languages[language].require)
|
|
||||||
promises.push(...results)
|
|
||||||
}
|
|
||||||
|
|
||||||
delete Prism.languages[language]
|
await import('prismjs/components/prism-' + lang)
|
||||||
if (!prismComponentCache.has(language)) {
|
defer.resolve({
|
||||||
await import('prismjs/components/prism-' + language)
|
lang,
|
||||||
prismComponentCache.set(language, Prism.languages[language])
|
status: loadedLanguages.has(lang) ? 'cached' : 'loaded'
|
||||||
} else {
|
|
||||||
Prism.languages[language] = prismComponentCache.get(language)
|
|
||||||
}
|
|
||||||
loadedCache.add(language)
|
|
||||||
promises.push(Promise.resolve({
|
|
||||||
status: 'loaded',
|
|
||||||
lang: language
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Reload dependents
|
|
||||||
const dependents = getPeerDependents(language).filter(function (dependent) {
|
|
||||||
// If dependent language was already loaded,
|
|
||||||
// we want to reload it.
|
|
||||||
if (Prism.languages[dependent]) {
|
|
||||||
delete Prism.languages[dependent]
|
|
||||||
loadedCache.delete(dependent)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
})
|
||||||
if (dependents.length) {
|
loadedLanguages.add(lang)
|
||||||
const results = await loadLanguages(dependents, true)
|
})
|
||||||
promises.push(...results)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ag-list-picker .item .icon-wrapper span:before {
|
.ag-list-picker .item .icon-wrapper span:before {
|
||||||
|
@ -48,19 +48,15 @@ class CodePicker extends BaseScrollFloat {
|
|||||||
const { renderArray, oldVnode, scrollElement, activeItem } = this
|
const { renderArray, oldVnode, scrollElement, activeItem } = this
|
||||||
let children = renderArray.map(item => {
|
let children = renderArray.map(item => {
|
||||||
let iconClassNames
|
let iconClassNames
|
||||||
if (item.ext && Array.isArray(item.ext)) {
|
|
||||||
for (const ext of item.ext) {
|
if (item.name) {
|
||||||
iconClassNames = fileIcons.getClassWithColor(`fackname.${ext}`)
|
iconClassNames = fileIcons.getClassByLanguage(item.name)
|
||||||
if (iconClassNames) break
|
|
||||||
}
|
|
||||||
} else if (item.name) {
|
|
||||||
iconClassNames = fileIcons.getClassWithColor(item.name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because `markdown mode in Codemirror` don't have extensions.
|
// Because `markdown mode in Codemirror` don't have extensions.
|
||||||
// if still can not get the className, add a common className 'atom-icon light-cyan'
|
// if still can not get the className, add a common className 'atom-icon light-cyan'
|
||||||
if (!iconClassNames) {
|
if (!iconClassNames) {
|
||||||
iconClassNames = item.name === 'markdown' ? fileIcons.getClassWithColor('fackname.md') : 'atom-icon light-cyan'
|
iconClassNames = item.name === 'markdown' ? fileIcons.getClassByName('fackname.md') : 'atom-icon light-cyan'
|
||||||
}
|
}
|
||||||
const iconSelector = 'span' + iconClassNames.split(/\s/).map(s => `.${s}`).join('')
|
const iconSelector = 'span' + iconClassNames.split(/\s/).map(s => `.${s}`).join('')
|
||||||
const icon = h('div.icon-wrapper', h(iconSelector))
|
const icon = h('div.icon-wrapper', h(iconSelector))
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
// Because the sidebar also use the file icons, So I put this file out of floatBox directory.
|
// Because the sidebar also use the file icons, So I put this file out of floatBox directory.
|
||||||
import 'file-icons-js/css/style.css'
|
import '@marktext/file-icons/build/index.css'
|
||||||
import fileIcons from 'file-icons-js'
|
import fileIcons from '@marktext/file-icons'
|
||||||
|
|
||||||
|
fileIcons.getClassByName = function (name) {
|
||||||
|
const icon = fileIcons.matchName(name)
|
||||||
|
|
||||||
|
return icon ? icon.getClass(0, false) : null
|
||||||
|
}
|
||||||
|
fileIcons.getClassByLanguage = function (lang) {
|
||||||
|
const icon = fileIcons.matchLanguage(lang)
|
||||||
|
|
||||||
|
return icon ? icon.getClass(0, false) : null
|
||||||
|
}
|
||||||
|
|
||||||
export default fileIcons
|
export default fileIcons
|
||||||
|
@ -412,3 +412,14 @@ export const collectFootnotes = (blocks) => {
|
|||||||
|
|
||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getDefer = () => {
|
||||||
|
const defer = {}
|
||||||
|
const promise = new Promise((resolve, reject) => {
|
||||||
|
defer.resolve = resolve
|
||||||
|
defer.reject = reject
|
||||||
|
})
|
||||||
|
defer.promise = promise
|
||||||
|
|
||||||
|
return defer
|
||||||
|
}
|
||||||
|
@ -15,10 +15,10 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
className () {
|
className () {
|
||||||
let icon = fileIcons.getClassWithColor(this.name ? this.name : 'mock.md')
|
let icon = fileIcons.getClassByName(this.name ? this.name : 'mock.md')
|
||||||
if (!icon) {
|
if (!icon) {
|
||||||
// Use fallback icon when the icon is unknown.
|
// Use fallback icon when the icon is unknown.
|
||||||
icon = fileIcons.getClassWithColor('mock.md')
|
icon = fileIcons.getClassByName('mock.md')
|
||||||
}
|
}
|
||||||
return icon.split(/\s/)
|
return icon.split(/\s/)
|
||||||
}
|
}
|
||||||
|
31
yarn.lock
31
yarn.lock
@ -1611,6 +1611,13 @@
|
|||||||
diff "^5.0.0"
|
diff "^5.0.0"
|
||||||
parse5-sax-parser "^6.0.1"
|
parse5-sax-parser "^6.0.1"
|
||||||
|
|
||||||
|
"@marktext/file-icons@^1.0.4":
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.npmjs.org/@marktext/file-icons/-/file-icons-1.0.4.tgz#322ab75e3d4c872550819b70f7dbe56e51322239"
|
||||||
|
integrity sha512-lVXig/OaF7JMPtxqd7InIraS1NcolXJBuBqlEet+Y8qgVsSns7DlNW876xo3Xywqf/hAuq1mQ4qjj/Gp97tcug==
|
||||||
|
dependencies:
|
||||||
|
file-icons "github:file-icons/atom"
|
||||||
|
|
||||||
"@nodelib/fs.scandir@2.1.3":
|
"@nodelib/fs.scandir@2.1.3":
|
||||||
version "2.1.3"
|
version "2.1.3"
|
||||||
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
|
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
|
||||||
@ -2773,6 +2780,13 @@ atob@^2.1.2:
|
|||||||
resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||||
|
|
||||||
|
atom-fs@v0.2.1:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.npmjs.org/atom-fs/-/atom-fs-0.2.1.tgz#650717ff1bfe2d10e3add5fa8f296875b68ce0e5"
|
||||||
|
integrity sha512-H+09ux1pNAPUbJqyrZ7lA/CpNmKqZURrYc23QzDUG29A380EYEnzwW99Do5VlT8SmZtyapOMySFesndgvZZGWg==
|
||||||
|
dependencies:
|
||||||
|
mapped-disposable "^1.0.3"
|
||||||
|
|
||||||
atomically@^1.7.0:
|
atomically@^1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe"
|
resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe"
|
||||||
@ -6531,10 +6545,14 @@ file-entry-cache@^6.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flat-cache "^3.0.4"
|
flat-cache "^3.0.4"
|
||||||
|
|
||||||
file-icons-js@1.0.3:
|
"file-icons@github:file-icons/atom":
|
||||||
version "1.0.3"
|
version "2.1.47"
|
||||||
resolved "https://registry.yarnpkg.com/file-icons-js/-/file-icons-js-1.0.3.tgz#d0765dc1d86aba4b2d7664a39e4ef7af9f12c5af"
|
resolved "https://codeload.github.com/file-icons/atom/tar.gz/66d57920f352fa5ed0c66f6fe86a98b2b3b8dac1"
|
||||||
integrity sha512-n4zoKEpMaAxBTUB7wtgrFBa4dM3b7mBLLA1VI/Q5Cdk/k2UA8S8oaxvnECp3QOzg0Dn+KKRzfIHF7qSdRkA65Q==
|
dependencies:
|
||||||
|
atom-fs v0.2.1
|
||||||
|
lru-cache "^5.1.1"
|
||||||
|
mapped-disposable "^1.0.3"
|
||||||
|
micromatch "^4.0.2"
|
||||||
|
|
||||||
file-loader@^6.2.0:
|
file-loader@^6.2.0:
|
||||||
version "6.2.0"
|
version "6.2.0"
|
||||||
@ -9321,6 +9339,11 @@ map-visit@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
object-visit "^1.0.0"
|
object-visit "^1.0.0"
|
||||||
|
|
||||||
|
mapped-disposable@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.npmjs.org/mapped-disposable/-/mapped-disposable-1.0.3.tgz#3eaad0b20b174142ee80bd37f675bab200abd569"
|
||||||
|
integrity sha512-DpYYRSZjNB6tOg8E4BZ+rNsKe4WxoptwM8+JqHi8R0buJgHLmrmAfJtv4lcqqO1esTtxaPx4FXOR54bPoS9qwg==
|
||||||
|
|
||||||
marked@^1.2.9:
|
marked@^1.2.9:
|
||||||
version "1.2.9"
|
version "1.2.9"
|
||||||
resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.9.tgz#53786f8b05d4c01a2a5a76b7d1ec9943d29d72dc"
|
resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.9.tgz#53786f8b05d4c01a2a5a76b7d1ec9943d29d72dc"
|
||||||
|
Loading…
Reference in New Issue
Block a user