From b2250b2b95d24f6e12033779d11fbccb3553a465 Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Sun, 6 Jul 2025 11:07:09 +0200 Subject: [PATCH] feat: add fontFamilies array --- .eslintrc.js | 68 ++++++++-------- src/components/FontChange.vue | 21 +++++ src/modules/repo/interfaces/UserSettings.ts | 6 +- src/modules/repo/services/repo.ts | 42 +++++----- src/modules/repo/store/userRepo.store.ts | 79 ++++++++++++------- .../user/hooks/useUserSettings.hook.ts | 14 ++-- src/utils/downloadGoogleFont.ts | 22 +++--- src/views/FleetingNotes.vue | 43 +++++----- 8 files changed, 169 insertions(+), 126 deletions(-) create mode 100644 src/components/FontChange.vue diff --git a/.eslintrc.js b/.eslintrc.js index 819e7d8..6b4f261 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,57 +1,53 @@ -require('@rushstack/eslint-patch/modern-module-resolution') +require("@rushstack/eslint-patch/modern-module-resolution") const DEV_TOOL_ACTIVATED = - process.env.NODE_ENV === 'production' ? 'warn' : 'off' + process.env.NODE_ENV === "production" ? "warn" : "off" module.exports = { root: true, env: { node: true, - es2022: true + es2022: true, }, - extends: [ - 'plugin:vue/vue3-essential', - 'eslint:recommended', - 'plugin:vue/recommended', - '@vue/typescript/recommended', - '@vue/eslint-config-typescript', - 'plugin:prettier-vue/recommended' - ], - plugins: ['simple-import-sort', 'unused-imports'], + extends: ["plugin:vue/vue3-essential", "@vue/eslint-config-typescript"], + plugins: ["simple-import-sort", "unused-imports"], rules: { - 'no-console': DEV_TOOL_ACTIVATED, - 'no-debugger': DEV_TOOL_ACTIVATED, - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/camelcase': 'off', - 'prettier-vue/prettier': [ - 'error', + "no-console": DEV_TOOL_ACTIVATED, + "no-debugger": DEV_TOOL_ACTIVATED, + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/camelcase": "off", + "prettier-vue/prettier": [ + "error", { semi: false, singleQuote: true, - trailingComma: 'none', - arrowParens: 'always' - } + trailingComma: "none", + arrowParens: "always", + }, ], - 'vue/no-v-html': 'off', - 'no-restricted-imports': [ - 'error', + "vue/no-v-html": "off", + "no-restricted-imports": [ + "error", { paths: [ { - name: 'vue-demi', - importNames: ['computed'], - message: 'Please use computed from vue instead.' - } - ] - } + name: "vue-demi", + importNames: ["computed"], + message: "Please use computed from vue instead.", + }, + ], + }, ], - 'simple-import-sort/imports': 'error', - 'simple-import-sort/exports': 'error', - 'unused-imports/no-unused-imports': 'error' + "simple-import-sort/imports": "error", + "simple-import-sort/exports": "error", + "unused-imports/no-unused-imports": "error", }, overrides: [ { - files: ['**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'] - } - ] + files: [ + "**/__tests__/*.{j,t}s?(x)", + "**/tests/unit/**/*.spec.{j,t}s?(x)", + ], + }, + ], } diff --git a/src/components/FontChange.vue b/src/components/FontChange.vue new file mode 100644 index 0000000..944385e --- /dev/null +++ b/src/components/FontChange.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/modules/repo/interfaces/UserSettings.ts b/src/modules/repo/interfaces/UserSettings.ts index 11e5569..1bf0235 100644 --- a/src/modules/repo/interfaces/UserSettings.ts +++ b/src/modules/repo/interfaces/UserSettings.ts @@ -1,8 +1,10 @@ -import { DataType } from '@/data/DataType.enum' -import { Model } from '@/data/models/Model' +import { DataType } from "@/data/DataType.enum" +import { Model } from "@/data/models/Model" export interface UserSettings extends Model { + fontFamilies?: string[] fontFamily?: string + chosenFontFamily?: string fontSize?: string backlink?: boolean } diff --git a/src/modules/repo/services/repo.ts b/src/modules/repo/services/repo.ts index 5381045..008aed7 100644 --- a/src/modules/repo/services/repo.ts +++ b/src/modules/repo/services/repo.ts @@ -1,21 +1,21 @@ -import { useMarkdown } from '@/hooks/useMarkdown.hook' -import { prepareNoteCache } from '@/modules/note/cache/prepareNoteCache' -import { RepoFile } from '@/modules/repo/interfaces/RepoFile' -import { UserSettings } from '@/modules/repo/interfaces/UserSettings' -import { getOctokit } from '@/modules/repo/services/octo' +import { useMarkdown } from "@/hooks/useMarkdown.hook" +import { prepareNoteCache } from "@/modules/note/cache/prepareNoteCache" +import { RepoFile } from "@/modules/repo/interfaces/RepoFile" +import { UserSettings } from "@/modules/repo/interfaces/UserSettings" +import { getOctokit } from "@/modules/repo/services/octo" export const getFiles = async ( owner: string, - repo: string + repo: string, ): Promise => { if (!owner || !repo) { return [] } const octokit = await getOctokit() - const commits = await octokit.request('GET /repos/{owner}/{repo}/commits', { + const commits = await octokit.request("GET /repos/{owner}/{repo}/commits", { owner, - repo + repo, }) const lastCommit = commits.data.shift() @@ -25,16 +25,16 @@ export const getFiles = async ( } const treeResponse = await octokit.request( - 'GET /repos/{owner}/{repo}/git/trees/{tree_sha}', + "GET /repos/{owner}/{repo}/git/trees/{tree_sha}", { owner, repo, tree_sha: lastCommit.commit.tree.sha, - recursive: 'true' - } + recursive: "true", + }, ) - return treeResponse?.data.tree.filter((t) => t.type === 'blob') ?? [] + return treeResponse?.data.tree.filter((t) => t.type === "blob") ?? [] } export const getCachedMainReadme = async (owner: string, repo: string) => { @@ -60,7 +60,7 @@ export const getMainReadme = async (owner: string, repo: string) => { const { render } = useMarkdown() const { getCachedNote, saveCacheNote } = prepareNoteCache( - `${owner}-${repo}-README` + `${owner}-${repo}-README`, ) try { @@ -68,7 +68,7 @@ export const getMainReadme = async (owner: string, repo: string) => { const README = await octokit.repos.getReadme({ owner, - repo + repo, }) if (README) { @@ -90,9 +90,9 @@ export const getMainReadme = async (owner: string, repo: string) => { export const getUserSettingsContent = async ( user: string, repo: string, - files: RepoFile[] -): Promise => { - const configFile = files.find((file) => file.path === '.litenote.json') + files: RepoFile[], +): Promise | null> => { + const configFile = files.find((file) => file.path === ".litenote.json") if (!configFile?.sha) { return null @@ -110,7 +110,7 @@ export const getUserSettingsContent = async ( export const queryFileContent = async ( user: string, repo: string, - sha: string + sha: string, ) => { const octokit = await getOctokit() @@ -119,12 +119,12 @@ export const queryFileContent = async ( } const file = await octokit.request( - 'GET /repos/{owner}/{repo}/git/blobs/{file_sha}', + "GET /repos/{owner}/{repo}/git/blobs/{file_sha}", { owner: user, repo: repo, - file_sha: sha - } + file_sha: sha, + }, ) return file?.data.content ?? null diff --git a/src/modules/repo/store/userRepo.store.ts b/src/modules/repo/store/userRepo.store.ts index e8d1ecb..5496ddc 100644 --- a/src/modules/repo/store/userRepo.store.ts +++ b/src/modules/repo/store/userRepo.store.ts @@ -1,17 +1,17 @@ -import { defineStore } from 'pinia' +import { defineStore } from "pinia" -import { data } from '@/data/data' -import { DataType } from '@/data/DataType.enum' -import { RepoFile } from '@/modules/repo/interfaces/RepoFile' -import { UserSettings } from '@/modules/repo/interfaces/UserSettings' -import { SavedRepo } from '@/modules/repo/models/SavedRepo' +import { data } from "@/data/data" +import { DataType } from "@/data/DataType.enum" +import { RepoFile } from "@/modules/repo/interfaces/RepoFile" +import { UserSettings } from "@/modules/repo/interfaces/UserSettings" +import { SavedRepo } from "@/modules/repo/models/SavedRepo" import { getCachedMainReadme, getFiles, getMainReadme, - getUserSettingsContent -} from '@/modules/repo/services/repo' -import { refreshToken } from '@/modules/user/service/signIn' + getUserSettingsContent, +} from "@/modules/repo/services/repo" +import { refreshToken } from "@/modules/user/service/signIn" interface State { user: string @@ -22,15 +22,14 @@ interface State { needToLogin: boolean } -export const useUserRepoStore = defineStore({ - id: 'USER_REPO_STATE', +export const useUserRepoStore = defineStore("USER_REPO_STATE", { state: (): State => ({ - user: '', - repo: '', + user: "", + repo: "", files: [], readme: undefined, userSettings: undefined, - needToLogin: false + needToLogin: false, }), actions: { async setUserRepo(user: string, repo: string) { @@ -39,7 +38,7 @@ export const useUserRepoStore = defineStore({ const savedRepoId = data.generateId(DataType.SavedRepo, `${user}-${repo}`) const cachedSavedRepo = await data.get( - savedRepoId + savedRepoId, ) if (cachedSavedRepo) { @@ -49,7 +48,7 @@ export const useUserRepoStore = defineStore({ try { await refreshToken() } catch (error) { - console.warn('impossible to refresh token', error) + console.warn("impossible to refresh token", error) } const userSettingsId = `UserSetting-${user}-${repo}` @@ -69,20 +68,30 @@ export const useUserRepoStore = defineStore({ $type: DataType.SavedRepo, repo, user, - files + files, }) this.files = files return getUserSettingsContent(user, repo, files) }) .then((userSettings) => { + const chosenFontFamily = userSettings?.fontFamilies?.find( + (font) => font === this.userSettings?.chosenFontFamily, + ) + ? this.userSettings?.chosenFontFamily + : userSettings?.fontFamily this.userSettings = userSettings - if (userSettings) { - data.update({ - ...userSettings, - _id: userSettingsId - }) + if (!this.userSettings) { + return } + + this.userSettings.chosenFontFamily = + chosenFontFamily ?? this.userSettings.fontFamily + + data.update({ + ...this.userSettings, + _id: userSettingsId, + }) }) getCachedMainReadme(user, repo).then(async (cachedReadme) => { @@ -101,11 +110,11 @@ export const useUserRepoStore = defineStore({ return } - console.log('add file') + console.log("add file") const savedRepoId = data.generateId( DataType.SavedRepo, - `${this.user}-${this.repo}` + `${this.user}-${this.repo}`, ) const newFiles = [...this.files.filter((f) => f.sha !== file.sha), file] data.update({ @@ -113,19 +122,31 @@ export const useUserRepoStore = defineStore({ $type: DataType.SavedRepo, repo: this.repo, user: this.user, - files: newFiles + files: newFiles, }) this.files = newFiles }, resetUserRepo() { - this.user = '' - this.repo = '' + this.user = "" + this.repo = "" this.resetFiles() }, resetFiles() { this.files = [] this.readme = null this.userSettings = undefined - } - } + }, + setFontFamily(fontFamily: string) { + if (!this.userSettings) { + return + } + this.userSettings.chosenFontFamily = fontFamily + + const userSettingsId = `UserSetting-${this.user}-${this.repo}` + data.update({ + ...this.userSettings, + _id: userSettingsId, + }) + }, + }, }) diff --git a/src/modules/user/hooks/useUserSettings.hook.ts b/src/modules/user/hooks/useUserSettings.hook.ts index 34a5c46..6a4dc18 100644 --- a/src/modules/user/hooks/useUserSettings.hook.ts +++ b/src/modules/user/hooks/useUserSettings.hook.ts @@ -1,10 +1,10 @@ -import { watchEffect } from 'vue' +import { watchEffect } from "vue" -import { useUserRepoStore } from '@/modules/repo/store/userRepo.store' -import { downloadGoogleFont } from '@/utils/downloadGoogleFont' +import { useUserRepoStore } from "@/modules/repo/store/userRepo.store" +import { downloadGoogleFont } from "@/utils/downloadGoogleFont" -const DEFAULT_FONT_POLICY = 'Courier Prime, monospace' -const DEFAULT_FONT_SIZE = '16px' +const DEFAULT_FONT_POLICY = "Courier Prime, monospace" +const DEFAULT_FONT_SIZE = "16px" export const useUserSettings = () => { const store = useUserRepoStore() @@ -16,10 +16,10 @@ export const useUserSettings = () => { const root = document.documentElement - const fontFamily = store.userSettings?.fontFamily + const fontFamily = store.userSettings?.chosenFontFamily const fontSize = store.userSettings?.fontSize downloadGoogleFont(fontFamily || DEFAULT_FONT_POLICY) - root.style.setProperty('--font-size', fontSize || DEFAULT_FONT_SIZE) + root.style.setProperty("--font-size", fontSize || DEFAULT_FONT_SIZE) }) } diff --git a/src/utils/downloadGoogleFont.ts b/src/utils/downloadGoogleFont.ts index 88130cb..2d472dc 100644 --- a/src/utils/downloadGoogleFont.ts +++ b/src/utils/downloadGoogleFont.ts @@ -1,4 +1,11 @@ -import FontFaceObserver from 'fontfaceobserver' +import FontFaceObserver from "fontfaceobserver" + +const assembleFontLink = (font: string) => { + return `https://fonts.googleapis.com/css2?display=swap&family=${font.replaceAll( + " ", + "+", + )}` +} export const downloadGoogleFont = async (font: string): Promise => { const href = assembleFontLink(font) @@ -7,21 +14,14 @@ export const downloadGoogleFont = async (font: string): Promise => { const existingLink = document.querySelector(`link[href="${href}"]`) if (!existingLink) { - const link = document.createElement('link') + const link = document.createElement("link") link.href = href - link.rel = 'stylesheet' + link.rel = "stylesheet" document.head.appendChild(link) } await new FontFaceObserver(font).load() - document.documentElement.style.setProperty('--font-family', font) -} - -const assembleFontLink = (font: string) => { - return `https://fonts.googleapis.com/css2?display=swap&family=${font.replaceAll( - ' ', - '+' - )}` + document.documentElement.style.setProperty("--font-family", font) } diff --git a/src/views/FleetingNotes.vue b/src/views/FleetingNotes.vue index 5c20e53..1722c08 100644 --- a/src/views/FleetingNotes.vue +++ b/src/views/FleetingNotes.vue @@ -1,17 +1,17 @@ @@ -69,11 +69,14 @@ watch(mode, async (newMode) => { :content="content" >

Inbox

-
+
- +
+ +