@themarioga/grid-editor 8.7.0 → 8.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/js/register.js", "../../src/js/plugins/grideditor.autosave.js"],
4
- "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * Autosave for grid-editor.\n *\n * A feature plugin: load this file after the editor and what is being edited\n * is kept in the browser's storage as it changes, and offered back the next\n * time an editor starts from the same html. What it can ask the editor for is\n * the handle its factory is called with, described in docs/plugins.md.\n *\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.autosave.min.js\"></script>\n *\n * It reads the canvas with ge.snapshotHtml(), which leaves the canvas\n * editing: the text being typed into stays open, with its cursor. A save\n * comes `delay` ms after the last change, and when the page is left.\n *\n * A draft remembers the html its editor started from, and is only offered\n * to an editor that starts from the same html: a page that loads one\n * document after another is not offered one document's draft over another.\n * Such a page gives each document a key of its own, and each keeps its draft.\n *\n * new GridEditor('#myGrid', { autosave: { key: 'page-42', storage: 'session' } });\n */\nimport { GridEditor } from '../grideditor.js';\n\nObject.assign(GridEditor.locales.en, {\n 'autosave.restore_title': 'Restore the draft?',\n 'autosave.restore_message': 'There is a draft of this page saved on {date}, with changes that were not published. Restore it?',\n 'autosave.restore': 'Restore',\n 'autosave.discard': 'Discard',\n});\n\nvar VERSION = 1;\nvar STORAGES = { local: 'localStorage', session: 'sessionStorage' };\nvar DEFAULT_DELAY = 1000;\n\n/** The keys the editors on this page save to: one editor to a key. */\nvar liveKeys = new Set();\n\n/** FNV-1a, 32 bits, as hex: enough to tell one document's html from another's. */\nfunction fingerprint(text) {\n var hash = 0x811c9dc5;\n\n for (var i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n\n return (hash >>> 0).toString(16).padStart(8, '0');\n}\n\n/** A stored value that is a draft this file wrote, or null. */\nfunction validDraft(value) {\n return !!value && typeof value === 'object' && value.version === VERSION &&\n typeof value.html === 'string' && typeof value.base === 'string' &&\n typeof value.savedAt === 'string' && !isNaN(Date.parse(value.savedAt));\n}\n\nGridEditor.features.autosave = function(ge) {\n\n var options = optionsFrom(ge.settings.autosave || {});\n var key = options.key || 'grideditor.autosave:' + window.location.pathname + '#' + ge.canvas.id;\n var storage = storageFor(options.storage);\n\n // unavailable | disabled | asking | enabled | destroyed\n var state = 'disabled';\n var enabledAfterAsking = true; // What asking ends in: a method may have changed it meanwhile\n var started = false; // Whether the first init has been looked at\n var draft = null; // The draft found when the editor was made, while it may be offered\n var base = null; // The fingerprint of the html the editor started from\n var last = null; // The html saved last, or the one there was to start from\n var timer = null;\n var observer = null;\n var sourceOpen = false;\n var warnedWrite = false;\n\n if (!storage) {\n ge.warn('autosave: the browser will not give this page its ' + STORAGES[options.storage] +\n ', so nothing is saved');\n state = 'unavailable';\n } else if (liveKeys.has(key)) {\n ge.warn('autosave: another editor on this page already saves to \"' + key + '\", so this one does not; ' +\n 'give each its own autosave.key');\n state = 'unavailable';\n } else {\n liveKeys.add(key);\n if (options.enabled) {\n state = 'enabled';\n draft = readDraft(true);\n }\n }\n\n function optionsFrom(given) {\n var result = {\n enabled: given.enabled === undefined ? true : !!given.enabled,\n storage: given.storage === undefined ? 'local' : given.storage,\n key: given.key === undefined ? null : given.key,\n delay: given.delay === undefined ? DEFAULT_DELAY : given.delay,\n maxAge: given.maxAge === undefined ? null : given.maxAge,\n };\n\n if (!STORAGES[result.storage]) {\n ge.warn('autosave.storage \"' + result.storage + '\" is not local or session: local is used');\n result.storage = 'local';\n }\n if (result.key !== null && (typeof result.key !== 'string' || result.key === '')) {\n ge.warn('autosave.key must be a string: the page\\'s own key is used');\n result.key = null;\n }\n if (typeof result.delay !== 'number' || !Number.isInteger(result.delay) || result.delay < 0) {\n ge.warn('autosave.delay must be a whole number of milliseconds, 0 or more: ' + DEFAULT_DELAY + ' is used');\n result.delay = DEFAULT_DELAY;\n }\n if (result.maxAge !== null && !(typeof result.maxAge === 'number' && isFinite(result.maxAge) && result.maxAge > 0)) {\n ge.warn('autosave.maxAge must be a number of milliseconds over 0, or null: drafts do not expire');\n result.maxAge = null;\n }\n\n return result;\n }\n\n /** The storage, if the browser lets the page have it. */\n function storageFor(name) {\n try {\n var found = window[STORAGES[name]];\n found.getItem(key);\n return found;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * The draft saved under the key, or null. Starting, one that cannot be\n * read or has expired is taken away: nothing will ever offer it.\n */\n function readDraft(starting) {\n var raw;\n\n try {\n raw = storage.getItem(key);\n } catch (error) {\n return null;\n }\n if (raw === null) { return null; }\n\n var value = null;\n try { value = JSON.parse(raw); } catch (error) { /* not ours, or mangled */ }\n\n if (!validDraft(value)) {\n if (starting) {\n ge.warn('autosave: what is saved under \"' + key + '\" is not a draft this version can read: it is discarded');\n remove();\n }\n return null;\n }\n\n if (starting && options.maxAge !== null && Date.now() - Date.parse(value.savedAt) > options.maxAge) {\n remove();\n return null;\n }\n\n return value;\n }\n\n function remove() {\n try { storage.removeItem(key); } catch (error) { /* nothing to take away */ }\n }\n\n /** Write the canvas as it is, if it changed. True when it was written. */\n function save(source) {\n window.clearTimeout(timer);\n timer = null;\n\n if (sourceOpen || base === null) { return false; }\n\n // The read itself may change the canvas - getHtml, when a plugin\n // cannot be read on a copy - and that is not a change to save\n var watching = !!observer;\n if (watching) { observer.disconnect(); }\n var html = ge.snapshotHtml();\n if (watching) { watch(); }\n\n if (html === last) { return false; }\n\n var value = { version: VERSION, html: html, savedAt: new Date().toISOString(), base: base };\n\n try {\n storage.setItem(key, JSON.stringify(value));\n } catch (error) {\n if (!warnedWrite) {\n warnedWrite = true;\n ge.warn('autosave: the draft could not be saved (' + (error && error.message || error) + ')');\n }\n ge.emit('autosave-error', { canvas: ge.canvas, error: error });\n return false;\n }\n\n last = html;\n ge.emit('after-autosave', { canvas: ge.canvas, html: html, savedAt: value.savedAt, source: source });\n return true;\n }\n\n function schedule() {\n window.clearTimeout(timer);\n timer = window.setTimeout(function() { save('change'); }, options.delay);\n }\n\n function watch() {\n if (!observer) { observer = new MutationObserver(schedule); }\n observer.observe(ge.canvas, { subtree: true, childList: true, attributes: true, characterData: true });\n }\n\n function unwatch() {\n window.clearTimeout(timer);\n timer = null;\n if (observer) { observer.disconnect(); }\n }\n\n function onPageHide() {\n if (state === 'enabled') { save('pagehide'); }\n }\n\n /** After the first init has finished: what there is to start from, and the draft offered. */\n function start() {\n if (state === 'destroyed' || state === 'unavailable') { return; }\n\n last = ge.snapshotHtml();\n base = fingerprint(last);\n window.addEventListener('pagehide', onPageHide);\n\n // One of another document, or the same as what is there, is not offered\n if (state === 'enabled' && draft && draft.base === base && draft.html !== last) {\n ask(draft);\n return;\n }\n\n draft = null;\n if (state === 'enabled') { watch(); }\n }\n\n function dateOf(savedAt) {\n try {\n return new Date(savedAt).toLocaleString(ge.settings.locale || undefined);\n } catch (error) {\n return new Date(savedAt).toLocaleString();\n }\n }\n\n function ask(found) {\n state = 'asking';\n\n ge.confirm(ge.t('autosave.restore_message', { date: dateOf(found.savedAt) }), {\n title: ge.t('autosave.restore_title'),\n ok: ge.t('autosave.restore'),\n cancel: ge.t('autosave.discard'),\n }, function(restore) {\n if (state === 'destroyed') { return; }\n\n // Taken away unanswered - setLocale - so asked again, in the new\n // language, once the old modal is out of the way\n if (restore === null) {\n window.setTimeout(function() {\n if (state === 'asking') { ask(found); }\n }, 0);\n return;\n }\n\n draft = null;\n\n if (restore) {\n last = found.html;\n ge.setHtml(found.html);\n ge.emit('after-restore-draft', { canvas: ge.canvas, html: found.html, savedAt: found.savedAt });\n } else {\n remove();\n }\n\n state = enabledAfterAsking ? 'enabled' : 'disabled';\n if (state === 'enabled') { watch(); }\n });\n }\n\n return {\n // The first init, once it has finished: the canvas is ready to be read\n onInit: function() {\n if (started) { return; }\n started = true;\n Promise.resolve().then(start);\n },\n\n onSourceOpen: function() { sourceOpen = true; },\n onSourceClose: function() { sourceOpen = false; },\n\n onDestroy: function() {\n if (state === 'enabled' && timer) { save('destroy'); }\n\n unwatch();\n observer = null;\n window.removeEventListener('pagehide', onPageHide);\n if (state !== 'unavailable') { liveKeys.delete(key); }\n state = 'destroyed';\n },\n\n methods: {\n enableAutosave: function() {\n if (state === 'unavailable') { return false; }\n if (state === 'asking') {\n enabledAfterAsking = true;\n return true;\n }\n if (state !== 'enabled') {\n state = 'enabled';\n if (base !== null) { watch(); }\n }\n return true;\n },\n\n disableAutosave: function() {\n if (state === 'unavailable') { return false; }\n if (state === 'asking') {\n enabledAfterAsking = false;\n return true;\n }\n unwatch();\n state = 'disabled';\n return true;\n },\n\n saveDraft: function() {\n if (state === 'unavailable' || state === 'asking') { return false; }\n return save('api');\n },\n\n getDraft: function() {\n if (state === 'unavailable') { return null; }\n\n var found = readDraft(false);\n return found ? { html: found.html, savedAt: found.savedAt } : null;\n },\n\n clearDraft: function() {\n if (state === 'unavailable') { return false; }\n\n remove();\n return true;\n },\n },\n };\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * Autosave for grid-editor.\n *\n * A feature plugin: load this file after the editor and what is being edited\n * is kept in the browser's storage as it changes, and offered back the next\n * time an editor starts from the same html. What it can ask the editor for is\n * the handle its factory is called with, described in docs/plugins.md.\n *\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.autosave.min.js\"></script>\n *\n * It reads the canvas with ge.snapshotHtml(), which leaves the canvas\n * editing: the text being typed into stays open, with its cursor. A save\n * comes `delay` ms after the last change, and when the page is left.\n *\n * A draft remembers the html its editor started from, and is only offered\n * to an editor that starts from the same html: a page that loads one\n * document after another is not offered one document's draft over another.\n * Such a page gives each document a key of its own, and each keeps its draft.\n *\n * new GridEditor('#myGrid', { autosave: { key: 'page-42', storage: 'session' } });\n */\nimport { GridEditor } from '../grideditor.js';\n\nObject.assign(GridEditor.locales.en, {\n 'autosave.restore_title': 'Restore the draft?',\n 'autosave.restore_message': 'There is a draft of this page saved on {date}, with changes that were not published. Restore it?',\n 'autosave.restore': 'Restore',\n 'autosave.discard': 'Discard',\n});\n\nvar VERSION = 1;\nvar STORAGES = { local: 'localStorage', session: 'sessionStorage' };\nvar DEFAULT_DELAY = 1000;\n\n/** The keys the editors on this page save to: one editor to a key. */\nvar liveKeys = new Set();\n\n/** FNV-1a, 32 bits, as hex: enough to tell one document's html from another's. */\nfunction fingerprint(text) {\n var hash = 0x811c9dc5;\n\n for (var i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n\n return (hash >>> 0).toString(16).padStart(8, '0');\n}\n\n/** A stored value that is a draft this file wrote, or null. */\nfunction validDraft(value) {\n return !!value && typeof value === 'object' && value.version === VERSION &&\n typeof value.html === 'string' && typeof value.base === 'string' &&\n typeof value.savedAt === 'string' && !isNaN(Date.parse(value.savedAt));\n}\n\nGridEditor.features.autosave = function(ge) {\n\n var options = optionsFrom(ge.settings.autosave || {});\n var key = options.key || 'grideditor.autosave:' + window.location.pathname + '#' + ge.canvas.id;\n var storage = storageFor(options.storage);\n\n // unavailable | disabled | asking | enabled | destroyed\n var state = 'disabled';\n var enabledAfterAsking = true; // What asking ends in: a method may have changed it meanwhile\n var started = false; // Whether the first init has been looked at\n var draft = null; // The draft found when the editor was made, while it may be offered\n var base = null; // The fingerprint of the html the editor started from\n var last = null; // The html saved last, or the one there was to start from\n var timer = null;\n var observer = null;\n var sourceOpen = false;\n var warnedWrite = false;\n\n if (!storage) {\n ge.warn('autosave: the browser will not give this page its ' + STORAGES[options.storage] +\n ', so nothing is saved');\n state = 'unavailable';\n } else if (liveKeys.has(key)) {\n ge.warn('autosave: another editor on this page already saves to \"' + key + '\", so this one does not; ' +\n 'give each its own autosave.key');\n state = 'unavailable';\n } else {\n liveKeys.add(key);\n if (options.enabled) {\n state = 'enabled';\n draft = readDraft(true);\n }\n }\n\n function optionsFrom(given) {\n var result = {\n enabled: given.enabled === undefined ? true : !!given.enabled,\n storage: given.storage === undefined ? 'local' : given.storage,\n key: given.key === undefined ? null : given.key,\n delay: given.delay === undefined ? DEFAULT_DELAY : given.delay,\n maxAge: given.maxAge === undefined ? null : given.maxAge,\n };\n\n if (!STORAGES[result.storage]) {\n ge.warn('autosave.storage \"' + result.storage + '\" is not local or session: local is used');\n result.storage = 'local';\n }\n if (result.key !== null && (typeof result.key !== 'string' || result.key === '')) {\n ge.warn('autosave.key must be a string: the page\\'s own key is used');\n result.key = null;\n }\n if (typeof result.delay !== 'number' || !Number.isInteger(result.delay) || result.delay < 0) {\n ge.warn('autosave.delay must be a whole number of milliseconds, 0 or more: ' + DEFAULT_DELAY + ' is used');\n result.delay = DEFAULT_DELAY;\n }\n if (result.maxAge !== null && !(typeof result.maxAge === 'number' && isFinite(result.maxAge) && result.maxAge > 0)) {\n ge.warn('autosave.maxAge must be a number of milliseconds over 0, or null: drafts do not expire');\n result.maxAge = null;\n }\n\n return result;\n }\n\n /** The storage, if the browser lets the page have it. */\n function storageFor(name) {\n try {\n var found = window[STORAGES[name]];\n found.getItem(key);\n return found;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * The draft saved under the key, or null. Starting, one that cannot be\n * read or has expired is taken away: nothing will ever offer it.\n */\n function readDraft(starting) {\n var raw;\n\n try {\n raw = storage.getItem(key);\n } catch (error) {\n return null;\n }\n if (raw === null) { return null; }\n\n var value = null;\n try { value = JSON.parse(raw); } catch (error) { /* not ours, or mangled */ }\n\n if (!validDraft(value)) {\n if (starting) {\n ge.warn('autosave: what is saved under \"' + key + '\" is not a draft this version can read: it is discarded');\n remove();\n }\n return null;\n }\n\n if (starting && options.maxAge !== null && Date.now() - Date.parse(value.savedAt) > options.maxAge) {\n remove();\n return null;\n }\n\n return value;\n }\n\n function remove() {\n try { storage.removeItem(key); } catch (error) { /* nothing to take away */ }\n }\n\n /** Write the canvas as it is, if it changed. True when it was written. */\n function save(source) {\n window.clearTimeout(timer);\n timer = null;\n\n if (sourceOpen || base === null) { return false; }\n\n // The read itself may change the canvas - getHtml, when a plugin\n // cannot be read on a copy - and that is not a change to save\n var watching = !!observer;\n if (watching) { observer.disconnect(); }\n var html = ge.snapshotHtml();\n if (watching) { watch(); }\n\n if (html === last) { return false; }\n\n var value = { version: VERSION, html: html, savedAt: new Date().toISOString(), base: base };\n\n try {\n storage.setItem(key, JSON.stringify(value));\n } catch (error) {\n if (!warnedWrite) {\n warnedWrite = true;\n ge.warn('autosave: the draft could not be saved (' + (error && error.message || error) + ')');\n }\n ge.emit('autosave-error', { canvas: ge.canvas, error: error });\n return false;\n }\n\n last = html;\n ge.emit('after-autosave', { canvas: ge.canvas, html: html, savedAt: value.savedAt, source: source });\n return true;\n }\n\n function schedule() {\n window.clearTimeout(timer);\n timer = window.setTimeout(function() { save('change'); }, options.delay);\n }\n\n function watch() {\n if (!observer) { observer = new MutationObserver(schedule); }\n observer.observe(ge.canvas, { subtree: true, childList: true, attributes: true, characterData: true });\n }\n\n function unwatch() {\n window.clearTimeout(timer);\n timer = null;\n if (observer) { observer.disconnect(); }\n }\n\n function onPageHide() {\n if (state === 'enabled') { save('pagehide'); }\n }\n\n /** After the first init has finished: what there is to start from, and the draft offered. */\n function start() {\n if (state === 'destroyed' || state === 'unavailable') { return; }\n\n last = ge.snapshotHtml();\n base = fingerprint(last);\n window.addEventListener('pagehide', onPageHide);\n\n // One of another document, or the same as what is there, is not offered\n if (state === 'enabled' && draft && draft.base === base && draft.html !== last) {\n ask(draft);\n return;\n }\n\n draft = null;\n if (state === 'enabled') { watch(); }\n }\n\n function dateOf(savedAt) {\n try {\n return new Date(savedAt).toLocaleString(ge.settings.locale || undefined);\n } catch (error) {\n return new Date(savedAt).toLocaleString();\n }\n }\n\n function ask(found) {\n state = 'asking';\n\n ge.confirm(ge.t('autosave.restore_message', { date: dateOf(found.savedAt) }), {\n title: ge.t('autosave.restore_title'),\n ok: ge.t('autosave.restore'),\n cancel: ge.t('autosave.discard'),\n }, function(restore) {\n if (state === 'destroyed') { return; }\n\n // Taken away unanswered - setLocale - so asked again, in the new\n // language, once the old modal is out of the way\n if (restore === null) {\n window.setTimeout(function() {\n if (state === 'asking') { ask(found); }\n }, 0);\n return;\n }\n\n draft = null;\n\n if (restore) {\n last = found.html;\n ge.setHtml(found.html);\n ge.emit('after-restore-draft', { canvas: ge.canvas, html: found.html, savedAt: found.savedAt });\n } else {\n remove();\n }\n\n state = enabledAfterAsking ? 'enabled' : 'disabled';\n if (state === 'enabled') { watch(); }\n });\n }\n\n return {\n // The first init, once it has finished: the canvas is ready to be read\n onInit: function() {\n if (started) { return; }\n started = true;\n Promise.resolve().then(start);\n },\n\n onSourceOpen: function() { sourceOpen = true; },\n onSourceClose: function() { sourceOpen = false; },\n\n onDestroy: function() {\n if (state === 'enabled' && timer) { save('destroy'); }\n\n unwatch();\n observer = null;\n window.removeEventListener('pagehide', onPageHide);\n if (state !== 'unavailable') { liveKeys.delete(key); }\n state = 'destroyed';\n },\n\n methods: {\n enableAutosave: function() {\n if (state === 'unavailable') { return false; }\n if (state === 'asking') {\n enabledAfterAsking = true;\n return true;\n }\n if (state !== 'enabled') {\n state = 'enabled';\n if (base !== null) { watch(); }\n }\n return true;\n },\n\n disableAutosave: function() {\n if (state === 'unavailable') { return false; }\n if (state === 'asking') {\n enabledAfterAsking = false;\n return true;\n }\n unwatch();\n state = 'disabled';\n return true;\n },\n\n saveDraft: function() {\n if (state === 'unavailable' || state === 'asking') { return false; }\n return save('api');\n },\n\n getDraft: function() {\n if (state === 'unavailable') { return null; }\n\n var found = readDraft(false);\n return found ? { html: found.html, savedAt: found.savedAt } : null;\n },\n\n // What there is now is not a draft any more - a page calls this\n // once it has saved to its server - so the save waiting does not\n // write it back, and only a change from here makes a new draft\n clearDraft: function() {\n if (state === 'unavailable') { return false; }\n\n window.clearTimeout(timer);\n timer = null;\n remove();\n\n // Not while it asks: the canvas is not what was offered yet\n if (base !== null && state !== 'asking' && !sourceOpen) {\n var watching = !!observer && state === 'enabled';\n if (watching) { observer.disconnect(); }\n last = ge.snapshotHtml();\n if (watching) { watch(); }\n }\n return true;\n },\n },\n };\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["GridEditor", "GridEditor", "VERSION", "STORAGES", "DEFAULT_DELAY", "liveKeys", "fingerprint", "text", "hash", "i", "validDraft", "value", "ge", "options", "optionsFrom", "key", "storage", "storageFor", "state", "enabledAfterAsking", "started", "draft", "base", "last", "timer", "observer", "sourceOpen", "warnedWrite", "readDraft", "given", "result", "name", "found", "error", "starting", "raw", "remove", "save", "source", "watching", "html", "watch", "schedule", "unwatch", "onPageHide", "start", "ask", "dateOf", "savedAt", "restore"]
7
7
  }
package/package.json CHANGED
@@ -32,7 +32,7 @@
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  },
35
- "version": "8.7.0",
35
+ "version": "8.7.1",
36
36
  "main": "dist/grideditor.js",
37
37
  "module": "dist/grideditor.esm.js",
38
38
  "types": "dist/grideditor.d.ts",
@@ -338,10 +338,23 @@ GridEditor.features.autosave = function(ge) {
338
338
  return found ? { html: found.html, savedAt: found.savedAt } : null;
339
339
  },
340
340
 
341
+ // What there is now is not a draft any more - a page calls this
342
+ // once it has saved to its server - so the save waiting does not
343
+ // write it back, and only a change from here makes a new draft
341
344
  clearDraft: function() {
342
345
  if (state === 'unavailable') { return false; }
343
346
 
347
+ window.clearTimeout(timer);
348
+ timer = null;
344
349
  remove();
350
+
351
+ // Not while it asks: the canvas is not what was offered yet
352
+ if (base !== null && state !== 'asking' && !sourceOpen) {
353
+ var watching = !!observer && state === 'enabled';
354
+ if (watching) { observer.disconnect(); }
355
+ last = ge.snapshotHtml();
356
+ if (watching) { watch(); }
357
+ }
345
358
  return true;
346
359
  },
347
360
  },