diff --git a/CHANGELOG.md b/CHANGELOG.md index 8874e82..deb26f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# 1.3.0 (04/11/2018) + +- css files can now be interpreted by the editable plugin when they change their extension to `sy` and set the type to `css` +- includes now outputs css styles with proper type tag (type='text/css') +- the editable plugin now allows type color to be passed +- the save action for form submission in serve is now actually async (it wasn't before, sometimes it would write sometimes it wouldn't) +- get and set now support mixed object access forms such as `obj.name` or `obj['name']` or `obj["name"]` + # 1.2.2 (04/11/2018) - if you edit something using editable view, it will write the wrong template to disk (this is fixed) @@ -6,7 +14,7 @@ - makes sure if the user had quotes on a variable in `.sweeney` that same quote / or not quote is persisted if updated. - this ensures if the value was a number it will be properly written - `templateToString` does not write type unless it was in options - + # 1.2.1 (04/11/2018) - removes `makeSearchable` migrates to `get` instead diff --git a/docs/assets/realtime-editing.png b/docs/assets/realtime-editing.png index acedead..4baa26c 100644 Binary files a/docs/assets/realtime-editing.png and b/docs/assets/realtime-editing.png differ diff --git a/example/.sweeney b/example/.sweeney index 8c61dbc..e1187cc 100644 --- a/example/.sweeney +++ b/example/.sweeney @@ -32,6 +32,11 @@ module.exports = async function() { user: { name: 'Gabriel J. Csapo', github_url: 'https://www.github.com/gabrielcsapo' + }, + colors: { + 'button-border':'#b3b3b3', + 'top-rect-start': '#1a1a1a', + 'top-rect-end': '#3e3e3e' } }, include: [ diff --git a/example/layouts/default.sy b/example/layouts/default.sy index 344ddae..13beda3 100644 --- a/example/layouts/default.sy +++ b/example/layouts/default.sy @@ -13,7 +13,7 @@ {{-- editable options.title || site.title string --}} - {{-- includes ../site.css --}} + {{-- includes ../styles/site.sy --}} diff --git a/example/site.css b/example/styles/site.sy similarity index 92% rename from example/site.css rename to example/styles/site.sy index dcb5e21..b301488 100644 --- a/example/site.css +++ b/example/styles/site.sy @@ -1,3 +1,9 @@ +--- +{ + "type": "css" +} +--- + * { font-family: Baskerville; font-weight: normal; @@ -17,8 +23,8 @@ html, body { top: 0; right: 0; z-index: -1; - background-color: #3e3e3e; - background: linear-gradient(to bottom right, #3e3e3e, #1a1a1a); + background-color: {{-- editable site.colors['top-rect-start'] color --}}; + background: linear-gradient(to bottom right, {{-- editable site.colors['top-rect-start'] color --}}, {{-- editable site.colors['top-rect-end'] color --}}); overflow: hidden; overflow-x: hidden; overflow-y: hidden; @@ -113,7 +119,7 @@ html, body { } .nav > .button { - border-color: #fff; + border-color: {{-- editable site.colors['button-border'] color --}}; color: #fff; font-size: 16px; } @@ -138,11 +144,6 @@ html, body { margin: 10px 5px; } -.button-getting-started { - width: 160px; - margin-top: 15px; -} - .button:hover { background: #3e3e3e; color: #ededed; diff --git a/lib/defaultPlugins.js b/lib/defaultPlugins.js index 06bbf57..c62d77a 100644 --- a/lib/defaultPlugins.js +++ b/lib/defaultPlugins.js @@ -1,14 +1,10 @@ -const fs = require('fs') const path = require('path') -const { promisify } = require('util') const { render, parse } = require('./util') -const readFile = promisify(fs.readFile) - module.exports.editable = { parse: async function (filePath, content) { - const reg = /{{-- editable (.+?) (string|number) --}}/g + const reg = /{{-- editable (.+?) (string|number|color) --}}/g if (content.match(reg)) { const found = [] @@ -37,7 +33,7 @@ module.exports.editable = { } // we want the parser to simply inject the required values back here, so just convert it to a basic variable template - content = content.replace(`{{-- editable ${variableName} ${type} --}}`, `{{ ${variableName} }}`) + content = content.replace(new RegExp(`{{-- editable ${variableName} ${type} --}}`.replace(/([.*+?^=!:${}()|[\]\\])/g, '\\$1'), 'g'), `{{ ${variableName} }}`) } return { content, @@ -73,9 +69,20 @@ module.exports.includes = { const start = process.hrtime() const ext = found.substring(found.lastIndexOf('.') + 1, found.length) const name = found.substring(found.lastIndexOf('/') + 1, found.length - 3) - const _content = await readFile(found, 'utf8') + // if the template isn't registered (ie it is somewhere else on disk and not in the site directory) go and parse that file + const _template = templates[name] || await parse(plugins, found) const depends = [] + if (ext === 'css') { + content = content.replace(`{{-- includes ${found} --}}`, ``) + + // ensure this content gets added to the dependency tree + depends.push({ + filePath: found, + time: process.hrtime(start)[1] / 1000000 + }) + } + if (ext === 'sy') { const passedData = Object.assign(data, { layout: '', @@ -83,24 +90,16 @@ module.exports.includes = { includes: [] }) - // if the template isn't registered (ie it is somewhere else on disk and not in the site directory) go and parse that file - const _template = templates[name] || await parse(plugins, found) const output = await render(plugins, templates, _template, passedData) // ensure this template gets added to the dependency tree depends.push(output) - content = content.replace(`{{-- includes ${found} --}}`, output.rendered) - } - - if (ext === 'css') { - content = content.replace(`{{-- includes ${found} --}}`, ``) - - // ensure this content gets added to the dependency tree - depends.push({ - filePath: found, - time: process.hrtime(start)[1] / 1000000 - }) + if (_template.type === 'css') { + content = content.replace(`{{-- includes ${found} --}}`, ``) + } else { + content = content.replace(`{{-- includes ${found} --}}`, output.rendered) + } } return { diff --git a/lib/serve/serve.js b/lib/serve/serve.js index 253fa0c..461ff3f 100644 --- a/lib/serve/serve.js +++ b/lib/serve/serve.js @@ -49,7 +49,9 @@ module.exports = async function ({ port, watch, site }) { } // We don't have to trigger a rebuild, since we are watching it should rebuild itself - Object.keys(fields).forEach(async (key) => { + const keys = Object.keys(fields) + for (var key of keys) { + console.log(key) if (key === 'filePath' || key === 'parentFilePath') return // only set the top level data on the config itself, everything else should be in the files @@ -57,12 +59,14 @@ module.exports = async function ({ port, watch, site }) { const configPath = path.resolve(site.source, '.sweeney') let rawConfig = await readFile(configPath, 'utf8') // we are only looking for the last value in the key string - const finalKey = key.substring(key.lastIndexOf('.') + 1, key.length) + const cleanedKey = key.replace(/(\[("|')*)/g, '.').replace(/("|')*(\])/g, '.').split('.').filter((k) => k !== '').join('.') + const finalKey = cleanedKey.substring(cleanedKey.lastIndexOf('.') + 1, cleanedKey.length) const previousValue = escapeRegexValues(get(site.config, key)) const reg = new RegExp(`(['|"]*)${finalKey}(['|"]*)\\s*:\\s*(['|"]*)${previousValue}(['|"]*)`) rawConfig = rawConfig.replace(reg, function (value, quote1, quote2, quote3, quote4) { return `${quote1}${finalKey}${quote2}:${quote3}${fields[key]}${quote4}` }) + console.log(rawConfig) await writeFile(configPath, rawConfig, 'utf8') delete require.cache[require.resolve(configPath)] @@ -77,7 +81,7 @@ module.exports = async function ({ port, watch, site }) { } }) } - }) + } res.writeHead(302, { 'Location': req.headers['referer'] @@ -149,7 +153,7 @@ module.exports = async function ({ port, watch, site }) { return `
  • - +
  • ` }).join('')} diff --git a/lib/util.js b/lib/util.js index 9a6f25c..400a004 100644 --- a/lib/util.js +++ b/lib/util.js @@ -395,7 +395,7 @@ function renderSubDepends (item, level = 0) { * @param {[type]} value [description] */ function set (obj, path, value) { - const pList = path.split('.') + const pList = path.replace(/(\[("|')*)/g, '.').replace(/("|')*(\])/g, '.').split('.').filter((k) => k !== '') const key = pList.pop() const pointer = pList.reduce((accumulator, currentValue) => { if (accumulator[currentValue] === undefined) accumulator[currentValue] = {} @@ -412,7 +412,7 @@ function set (obj, path, value) { * @return {[type]} [description] */ function get (obj, path) { - const pList = path.split('.') + const pList = path.replace(/(\[("|')*)/g, '.').replace(/("|')*(\])/g, '.').split('.').filter((k) => k !== '') const key = pList.pop() const pointer = pList.reduce((accumulator, currentValue) => { if (accumulator[currentValue] === undefined) accumulator[currentValue] = {} diff --git a/package.json b/package.json index 9642b41..ac512ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sweeney", - "version": "1.2.2", + "version": "1.3.0", "description": "💈 A static site generator that cuts the way you want it to", "author": "Gabriel J. Csapo ", "license": "Apache-2.0", diff --git a/test/defaultPlugins.js b/test/defaultPlugins.js index 82fb2b6..2152f28 100644 --- a/test/defaultPlugins.js +++ b/test/defaultPlugins.js @@ -93,7 +93,7 @@ test('@defaultPlugins', (t) => { t.deepEqual(output.depends.length, 1) t.equal(output.depends[0].filePath, path.resolve(__dirname, 'fixtures', 'test.css')) - t.deepEqual(output.content, `\n \n\n \n \n \n \n\n {{ options.title || site.title }}\n \n \n \n\n\n \n {{-- includes ${path.resolve(__dirname)}/fixtures/nav.sy --}}\n\n
    \n
    \n
    \n {{ child }}\n
    \n\n \n
    \n \n\n `) + t.deepEqual(output.content, `\n \n\n \n \n \n \n\n {{ options.title || site.title }}\n \n \n \n\n\n \n {{-- includes ${path.resolve(__dirname)}/fixtures/nav.sy --}}\n\n
    \n
    \n
    \n {{ child }}\n
    \n\n \n
    \n \n\n `) t.end() }) diff --git a/test/util.js b/test/util.js index 6ba8b43..9b5f306 100644 --- a/test/util.js +++ b/test/util.js @@ -527,7 +527,7 @@ test('util', (t) => { 'posts', 'posts.sy', 'projects.sy', - 'site.css', + 'styles', 'sweeney.svg' ])