Skip to content

Commit bec720c

Browse files
committed
feat: Add urlSync config
1 parent 4827905 commit bec720c

File tree

12 files changed

+126
-27
lines changed

12 files changed

+126
-27
lines changed

index.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@
430430
</label>
431431
</div>
432432
</div>
433+
433434
<div class="settings-item">
434435
<strong>
435436
<span class="settings-type" data-translate="featuresAutosave">Features › Auto save:</span>
@@ -443,6 +444,21 @@
443444
</label>
444445
</div>
445446
</div>
447+
448+
<div class="settings-item">
449+
<strong>
450+
<span class="settings-type" data-translate="features">Features:</span>
451+
<span data-translate="urlSync">URL Sync</span>
452+
</strong>
453+
<label class="checkbox">
454+
<input name="urlSync" type="checkbox" />
455+
<span data-translate="urlSyncCheckbox">Automatically update URL</span>
456+
</label>
457+
<p class="setting-description" data-translate="urlSyncDescription">
458+
Keeps the URL in sync with your current code for easy sharing. Disable to
459+
prevent flooding your browser history.
460+
</p>
461+
</div>
446462
</div>
447463
</form>
448464
</div>

src/aside.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { eventBus, EVENTS } from './events-controller.js'
22
import { $, $$ } from './utils/dom.js'
33
import * as Preview from './utils/WindowPreviewer'
44
import { BUTTON_ACTIONS } from './constants/button-actions.js'
5-
import { copyToClipboard } from './utils/string.js'
65
import { resetConsoleBadge } from './console.js'
76

87
const $aside = $('aside')
@@ -23,10 +22,8 @@ const SIMPLE_CLICK_ACTIONS = {
2322
Preview.showPreviewerWindow()
2423
},
2524

26-
[BUTTON_ACTIONS.copyToClipboard]: async () => {
27-
const url = new URL(window.location.href)
28-
const urlToCopy = `https://codi.link${url.pathname}`
29-
copyToClipboard(urlToCopy)
25+
[BUTTON_ACTIONS.copyToClipboard]: () => {
26+
eventBus.emit(EVENTS.COPY_CURRENT_CODE_URL)
3027
},
3128

3229
[BUTTON_ACTIONS.clearHistory]: () => {

src/components/codi-editor/extensions/editor-hotkeys.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as monaco from 'monaco-editor'
22
import { $ } from '../../../utils/dom.js'
3-
import { copyToClipboard } from '../../../utils/string'
3+
import { eventBus, EVENTS } from '../../../events-controller.js'
44

55
export const initEditorHotKeys = (editor) => {
66
// Shortcut: Open/Close Settings
@@ -22,9 +22,7 @@ export const initEditorHotKeys = (editor) => {
2222
editor.addCommand(
2323
monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KeyC,
2424
() => {
25-
const url = new URL(window.location.href)
26-
const urlToCopy = `https://codi.link${url.pathname}`
27-
copyToClipboard(urlToCopy)
25+
eventBus.emit(EVENTS.COPY_CURRENT_CODE_URL)
2826
}
2927
)
3028
}

src/constants/initial-settings.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const DEFAULT_INITIAL_SETTINGS = {
1717
zipFileName: 'codi.link',
1818
zipInSingleFile: false,
1919
saveLocalstorage: true,
20+
urlSync: true,
2021
layout: {
2122
gutters: DEFAULT_LAYOUT,
2223
style: DEFAULT_GRID_TEMPLATE,

src/events-controller.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { decode } from 'js-base64'
2-
import { capitalize, searchByLine } from './utils/string.js'
2+
import { capitalize, copyToClipboard, searchByLine } from './utils/string.js'
3+
import { getEncodedPath } from './utils/url.js'
34
import { downloadUserCode } from './download.js'
45
import { getState } from './state.js'
56
import { getHistoryState } from './history.js'
@@ -42,6 +43,7 @@ export const EVENTS = {
4243
DRAG_FILE: 'DRAG_FILE',
4344
OPEN_EXISTING_INSTANCE: 'OPEN_EXISTING_INSTANCE',
4445
OPEN_NEW_INSTANCE: 'OPEN_NEW_INSTANCE',
46+
COPY_CURRENT_CODE_URL: 'COPY-CURRENT-CODE-URL',
4547
CLEAR_HISTORY: 'CLEAR_HISTORY'
4648
}
4749

@@ -122,3 +124,15 @@ eventBus.on(EVENTS.CLEAR_HISTORY, () => {
122124
const { clearHistory } = getHistoryState()
123125
clearHistory()
124126
})
127+
128+
eventBus.on(EVENTS.COPY_CURRENT_CODE_URL, async () => {
129+
const html = htmlEditor.getValue()
130+
const css = cssEditor.getValue()
131+
const js = jsEditor.getValue()
132+
133+
const encodedPath = getEncodedPath({ html, css, js })
134+
135+
const urlToCopy = `${window.location.origin}${encodedPath}`
136+
137+
await copyToClipboard(urlToCopy)
138+
})

src/language/en.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ const en = {
6161
localStorage: 'Local storage',
6262
automaticallySaveUrl:
6363
'Automatically save URL to local storage for fast content loading',
64+
features: 'Features',
65+
urlSync: 'URL Sync',
66+
urlSyncCheckbox: 'Automatically update URL',
67+
urlSyncDescription: 'Keeps the URL in sync with your current code for easy sharing. Disable to prevent flooding your browser history.',
6468
searchDependency: 'Search and add a package...'
6569
}
6670

src/language/es.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ const es = {
6161
localStorage: 'Almacenamiento local',
6262
automaticallySaveUrl:
6363
'Guardar automáticamente la URL en el almacenamiento local para una carga rápida del contenido',
64+
features: 'Características',
65+
urlSync: 'URL Sync',
66+
urlSyncCheckbox: 'Actualizar URL automáticamente',
67+
urlSyncDescription:
68+
'Actualiza automáticamente la URL con tu código actual. Desactívalo para evitar saturar el historial de navegación.',
6469
searchDependency: 'Buscar y agregar un paquete...'
6570
}
6671

src/language/pt.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ const pt = {
6161
localStorage: 'Armazenamento local',
6262
automaticallySaveUrl:
6363
'Salvar automaticamente a URL no armazenamento local para carregamento rápido de conteúdo',
64+
features: 'Recursos',
65+
urlSync: 'URL Sync',
66+
urlSyncCheckbox: 'Atualizar automaticamente a URL',
67+
urlSyncDescription:
68+
'Atualiza automaticamente a URL com o código atual. Desative para evitar sobrecarregar o histórico do navegador.',
6469
searchDependency: 'Pesquisar e adicionar um pacote...'
6570
}
6671

src/main.js

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { encode, decode } from 'js-base64'
1+
import { decode } from 'js-base64'
22
import { $, $$ } from './utils/dom.js'
33
import { createEditor } from './editor.js'
44
import debounce from './utils/debounce.js'
@@ -11,6 +11,8 @@ import setTheme from './theme.js'
1111
import setLanguage from './language.js'
1212
import { configurePrettierHotkeys } from './monaco-prettier/configurePrettier'
1313
import { getHistoryState, subscribeHistory, setHistory } from './history.js'
14+
import { getEncodedString } from './utils/url.js'
15+
import { setUrlSync, handleUrlSyncOnType } from './url-sync.js'
1416

1517
import './aside.js'
1618
import './skypack.js'
@@ -70,15 +72,11 @@ subscribe(state => {
7072
setGridLayout(state.layout)
7173
setTheme(state.theme)
7274
setLanguage(state.language)
75+
setUrlSync(state.urlSync, EDITORS)
7376
})
7477

7578
const MS_UPDATE_DEBOUNCED_TIME = 200
76-
const MS_UPDATE_HASH_DEBOUNCED_TIME = 1000
7779
const debouncedUpdate = debounce(update, MS_UPDATE_DEBOUNCED_TIME)
78-
const debouncedUpdateHash = debounce(
79-
updateHashedCode,
80-
MS_UPDATE_HASH_DEBOUNCED_TIME
81-
)
8280

8381
const { html: htmlEditor, css: cssEditor, javascript: jsEditor } = EDITORS
8482

@@ -116,8 +114,9 @@ function update ({ notReload } = {}) {
116114

117115
Preview.updatePreview(values)
118116

117+
const { maxExecutionTime, urlSync } = getState()
118+
119119
if (!notReload) {
120-
const { maxExecutionTime } = getState()
121120
runJs(values.js, parseInt(maxExecutionTime))
122121
.then(() => {
123122
iframe.setAttribute('src', Preview.getPreviewUrl())
@@ -129,10 +128,17 @@ function update ({ notReload } = {}) {
129128

130129
updateCss()
131130

132-
debouncedUpdateHash(values)
133131
if (saveLocalstorage) {
134132
updateHistory(values)
135133
}
134+
135+
if (urlSync) {
136+
handleUrlSyncOnType(values)
137+
}
138+
139+
// fixes url bugs when using history
140+
setUrlSync(urlSync, EDITORS)
141+
136142
updateButtonAvailabilityIfContent(values)
137143
}
138144

@@ -144,14 +150,9 @@ function updateCss () {
144150
}
145151
}
146152

147-
function updateHashedCode ({ html, css, js }) {
148-
const hashedCode = `${encode(html)}|${encode(css)}|${encode(js)}`
149-
window.history.replaceState(null, null, `/${hashedCode}`)
150-
}
151-
152153
function updateHistory ({ html, css, js }) {
153154
const { history } = getHistoryState()
154-
const hashedCode = `${encode(html)}|${encode(css)}|${encode(js)}`
155+
const hashedCode = getEncodedString({ html, css, js })
155156
const isEmpty = !html.replace(/\n/g, '').trim() && !css.replace(/\n/g, '').trim() && !js.replace(/\n/g, '').trim()
156157

157158
if (isEmpty && !history.current) {

src/url-sync.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { getCleanPath, getEncodedPath } from './utils/url.js'
2+
import debounce from './utils/debounce.js'
3+
4+
const MS_UPDATE_HASH_DEBOUNCED_TIME = 1000
5+
6+
function getCurrentCodeFromEditors (EDITORS) {
7+
return {
8+
html: EDITORS.html?.getValue() || '',
9+
css: EDITORS.css?.getValue() || '',
10+
js: EDITORS.javascript?.getValue() || ''
11+
}
12+
}
13+
14+
function updateHashedPath ({ html, css, js }) {
15+
window.history.replaceState(null, null, getEncodedPath({ html, css, js }))
16+
}
17+
18+
const debouncedUpdateHashedPath = debounce(updateHashedPath, MS_UPDATE_HASH_DEBOUNCED_TIME)
19+
20+
export function handleUrlSyncOnType (codeValues) {
21+
debouncedUpdateHashedPath(codeValues)
22+
}
23+
24+
export function setUrlSync (isUrlSyncEnabled, EDITORS) {
25+
const currentPathIsEmpty = window.location.pathname === '/'
26+
27+
const shouldEncodeUrl = isUrlSyncEnabled && currentPathIsEmpty
28+
const shouldCleanUrl = !isUrlSyncEnabled && !currentPathIsEmpty
29+
30+
if (shouldEncodeUrl) {
31+
const { html, css, js } = getCurrentCodeFromEditors(EDITORS)
32+
window.history.replaceState(null, null, getEncodedPath({ html, css, js }))
33+
return
34+
}
35+
36+
if (shouldCleanUrl) {
37+
window.history.replaceState(null, null, getCleanPath())
38+
}
39+
}

0 commit comments

Comments
 (0)