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:
Ran Luo 2021-12-26 16:21:00 +08:00 committed by GitHub
parent c6d4368988
commit 8af9605e35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2266 additions and 2329 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,77 +37,48 @@ 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
}
// handle already cached
if (loadedCache.has(language)) {
promises.push(Promise.resolve({
lang: language,
status: 'cached'
}))
continue
}
// Load dependencies first
if (!withoutDependencies && languages[language].require) {
const results = await loadLanguages(languages[language].require)
promises.push(...results)
}
delete Prism.languages[language]
if (!prismComponentCache.has(language)) {
await import('prismjs/components/prism-' + language)
prismComponentCache.set(language, Prism.languages[language])
} 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) { return
const results = await loadLanguages(dependents, true)
promises.push(...results)
}
} }
delete Prism.languages[lang]
await import('prismjs/components/prism-' + lang)
defer.resolve({
lang,
status: loadedLanguages.has(lang) ? 'cached' : 'loaded'
})
loadedLanguages.add(lang)
})
return Promise.all(promises) return Promise.all(promises)
} }
} }

View File

@ -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 {

View File

@ -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))

View File

@ -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

View File

@ -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
}

View File

@ -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/)
} }

View File

@ -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"