├── .gitignore ├── README.md ├── assets ├── alignment_toolbar.png ├── css │ └── style.css ├── custom_block_sidebar.png ├── insert_custom_block.gif ├── js │ ├── script.js │ └── script.min.js ├── screenshot-1.gif ├── source │ ├── js │ │ ├── admin-notice.js │ │ ├── block-component.js │ │ ├── block-details.js │ │ ├── explorer-filter.js │ │ └── script.js │ └── scss │ │ ├── style.css │ │ └── style.scss └── thumbnail.png ├── cloud-blocks.php ├── composer.json ├── composer.lock ├── core ├── Activator.php ├── Blocks │ ├── Blocks.php │ ├── Explore.php │ └── Options.php ├── CloudBlocks.php ├── Settings │ ├── Tools.php │ └── Translations.php └── Uninstall.php ├── docs ├── changelog.md ├── create-block.md ├── hooks.md ├── migrate-block.md └── private-blocks.md ├── languages ├── cloud-blocks-it_IT.mo ├── cloud-blocks-it_IT.po ├── cloud-blocks-nb_NO.mo ├── cloud-blocks-nb_NO.po ├── cloud-blocks-pl_PL.mo ├── cloud-blocks-pl_PL.po ├── cloud-blocks-pt.mo ├── cloud-blocks-pt.po ├── cloud-blocks-pt_PT.mo └── cloud-blocks-pt_PT.po ├── package-lock.json ├── package.json ├── readme.txt └── vendor ├── autoload.php ├── composer ├── ClassLoader.php ├── LICENSE ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php ├── autoload_static.php └── installed.json └── foadyousefi └── seven-fields ├── README.md ├── VERSION ├── assets └── css │ └── styles.css ├── composer.json ├── config.php └── src ├── Bootstrap └── Bootstrap.php ├── Container └── Container.php └── Fields ├── Checkbox.php ├── Fields.php ├── Header.php ├── Html.php ├── Multiselect.php ├── Select.php ├── Text.php └── Textarea.php /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cloud Blocks 2 | 3 | ## Description 4 | 5 | **Gutenberg Cloud: Your online library of blocks!** Cloud Blocks is the only plugin you need to browse and install new blocks: 6 | 7 | - Discover and install custom blocks with a click 8 | - Install only the blocks you need – no huge plugin collections needed 9 | - Reuse blocks between WordPress and Drupal 10 | - Serve the blocks from a CDN 11 | 12 | ### Why use Gutenberg Cloud? 13 | Installing an actual plugin for each block or block collection easily leads to managing lots of code that you don’t really need. It’s like having one app for each website you visit, instead of just installing a web browser. With the block manager, you have a growing library at your fingertips, without the bloat. 14 | 15 | ## Getting started 16 | 1. Install the plugin 17 | 2. Click the new cloud icon in the main menu 18 | 3. Browse around and click a block to see description, version and bigger screenshot 19 | 4. Activate a few blocks. Voila – these are now available to you in the Gutenberg editor! 20 | 21 | ### How it works under the hood 22 | Gutenberg Cloud is a service that fetches Open Source Gutenberg blocks hosted on NPM. The assets from these are served from CloudFlare using jsdelivr.com. The Cloud Blocks plugin provides an interface in WordPress for Gutenberg Cloud. 23 | 24 | Code once, use everywhere: Since the blocks are JS/CSS only, they are CMS agnostic. This means you can develop a block for a Drupal site, and reuse it later on a WordPress blog. 25 | 26 | ## Installation 27 | Install it as any other plugin, but note that you need Gutenberg activated for it to work. 28 | 29 | To install individual blocks, look for the cloud icon in the left side menu. Click it, and browse away! 30 | 31 | ## Frequently Asked Questions 32 | 33 | **Is it secure to run blocks from other people?** 34 | 35 | All blocks go through a manual code review before they are published. Waiting for a code review? Email perandre@front.no. 36 | 37 | **How do I migrate a block collection plugin to Gutenberg Cloud?** 38 | 39 | This simply means removing some PHP, adding some meta data and publishing on NPM. [Follow these simple steps](https://github.com/front/cloud-blocks/blob/master/docs/migrate-block.md). 40 | 41 | **How do I create a custom block for Gutenberg Cloud?** 42 | 43 | Gutenberg Cloud blocks are really just normal Gutenberg blocks, without the PHP. [Follow these steps to do it](https://github.com/front/cloud-blocks/blob/master/docs/create-block.md)! 44 | 45 | **How do I disable CSS for a single block?** 46 | 47 | This is useful for letting your theme control your block styles. There’s a hook for this, [documented here](https://github.com/front/cloud-blocks/blob/master/docs/hooks.md). 48 | 49 | **Why is the plugin called Cloud Blocks?** 50 | 51 | We wanted to name it Gutenberg Cloud, but since it’s not possible to name a plugin starting with the name of another plugin (i.e. Gutenberg), we ended up calling it Cloud Blocks. Makes sense though, doesn’t it? 52 | 53 | **Are the blocks really served from "the cloud"?** 54 | 55 | Indeed, they are! The source code for each block is on NPM, but the JS/CSS is served by a CDN. No local downloads! 56 | 57 | **Can I add private custom blocks?** 58 | 59 | Sure! Just add your custom blocks into **wp-content/uploads/gutenberg-blocks/** folder. All your private blocks will be listed under `Local` tab in block explorer which you can activate/deactivate them. In order for your block to be active in the Gutenberg panel, it should be installed in Gutenberg Cloud. [This is what the folder structure should look like](https://github.com/front/cloud-blocks/blob/master/docs/private-blocks.md)! 60 | 61 | 62 | ## Changelog 63 | 64 | Since changelog is getting too long to fit here, we moved it into its own file [here](https://github.com/front/cloud-blocks/blob/master/docs/changelog.md). 65 | -------------------------------------------------------------------------------- /assets/alignment_toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/assets/alignment_toolbar.png -------------------------------------------------------------------------------- /assets/css/style.css: -------------------------------------------------------------------------------- 1 | [v-cloak] > * { 2 | display: none; } 3 | 4 | .g-blocks-filter { 5 | padding-left: 20px; } 6 | 7 | .block-version, 8 | .block-author { 9 | position: absolute; 10 | top: 15px; 11 | right: 20px; } 12 | 13 | .spinner.installing-block { 14 | visibility: inherit; 15 | position: absolute; 16 | top: 50%; 17 | left: 50%; 18 | -webkit-transform: translate(-50%, -50%); 19 | transform: translate(-50%, -50%); } 20 | 21 | .install-block-btn.button-delete { 22 | color: #fff; 23 | border-color: #E91E63; 24 | background: #E91E63; 25 | box-shadow: 0 1px 0 #E91E63; 26 | vertical-align: top; } 27 | .install-block-btn.button-delete:hover { 28 | color: #fff; 29 | border-color: #ab194a; 30 | background: #c22057; 31 | box-shadow: 0 1px 0 #cc1a56; 32 | vertical-align: top; } 33 | 34 | .fgc-notification { 35 | visibility: hidden; 36 | min-width: 300px; 37 | background-color: #333; 38 | color: #fff; 39 | text-align: center; 40 | border-radius: 2px; 41 | padding: 10px 24px; 42 | position: fixed; 43 | z-index: 100000; 44 | left: 50%; 45 | -webkit-transform: translateX(-50%); 46 | transform: translateX(-50%); 47 | bottom: 30px; } 48 | 49 | .fgc-notification.success { 50 | background-color: #1883db; } 51 | 52 | .fgc-notification.error { 53 | background-color: #d1554c; } 54 | 55 | .fgc-notification.show { 56 | visibility: visible; 57 | -webkit-animation: fadein 0.5s, fadeout 0.5s 3.5s; 58 | animation: fadein 0.5s, fadeout 0.5s 3.5s; } 59 | 60 | @-webkit-keyframes fadein { 61 | from { 62 | bottom: 0; 63 | opacity: 0; } 64 | to { 65 | bottom: 30px; 66 | opacity: 1; } } 67 | 68 | @keyframes fadein { 69 | from { 70 | bottom: 0; 71 | opacity: 0; } 72 | to { 73 | bottom: 30px; 74 | opacity: 1; } } 75 | 76 | @-webkit-keyframes fadeout { 77 | from { 78 | bottom: 30px; 79 | opacity: 1; } 80 | to { 81 | bottom: 0; 82 | opacity: 0; } } 83 | 84 | @keyframes fadeout { 85 | from { 86 | bottom: 30px; 87 | opacity: 1; } 88 | to { 89 | bottom: 0; 90 | opacity: 0; } } 91 | 92 | .fgc-wrapper-grid { 93 | margin-left: 8px; 94 | margin-right: 8px; 95 | margin-top: 10px; } 96 | .fgc-wrapper-grid .postbox { 97 | float: left; 98 | clear: left; 99 | width: 50%; 100 | margin: 0 0 16px; } 101 | @media only screen and (max-width: 850px) { 102 | .fgc-wrapper-grid .postbox { 103 | margin-left: 0 !important; 104 | margin-right: 0 !important; 105 | width: 100%; } } 106 | .fgc-wrapper-grid .postbox .inside { 107 | margin-bottom: 0; } 108 | .fgc-wrapper-grid .postbox:nth-child(odd) { 109 | margin-left: -8px; } 110 | .fgc-wrapper-grid .postbox:nth-child(even) { 111 | float: right; 112 | clear: right; 113 | margin-right: -8px; } 114 | .fgc-wrapper-grid .hndle { 115 | font-size: 14px; 116 | padding: 8px 12px; 117 | margin: 0; 118 | line-height: 1.4; } 119 | .fgc-wrapper-grid .fgc-fields { 120 | border: #ebebeb solid 1px; 121 | background: #fafafa; 122 | border-radius: 3px; } 123 | 124 | .fgc-center-text { 125 | text-align: center; } 126 | 127 | .upload-custom-block .block-install-help code { 128 | font-size: 12px; } 129 | -------------------------------------------------------------------------------- /assets/custom_block_sidebar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/assets/custom_block_sidebar.png -------------------------------------------------------------------------------- /assets/insert_custom_block.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/assets/insert_custom_block.gif -------------------------------------------------------------------------------- /assets/screenshot-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/assets/screenshot-1.gif -------------------------------------------------------------------------------- /assets/source/js/admin-notice.js: -------------------------------------------------------------------------------- 1 | Vue.component('admin-notice', { 2 | data() { 3 | return { 4 | activeTimeout: -1 5 | } 6 | }, 7 | template: ` 8 |
11 |

12 |
13 | `, 14 | watch: { 15 | isActive () { 16 | this.showingTimeout() 17 | } 18 | }, 19 | mounted() { 20 | this.showingTimeout() 21 | }, 22 | methods: { 23 | showingTimeout() { 24 | window.clearTimeout(this.activeTimeout) 25 | this.activeTimeout = window.setTimeout(() => { 26 | window.store.state.notification.class = '' 27 | this.isShowing = false 28 | }, 4000) 29 | } 30 | }, 31 | computed: { 32 | isActive() { 33 | return window.store.state.notification.text 34 | }, 35 | notification() { 36 | return window.store.state.notification 37 | } 38 | } 39 | }) 40 | -------------------------------------------------------------------------------- /assets/source/js/block-component.js: -------------------------------------------------------------------------------- 1 | Vue.component('block-card', { 2 | props: ['block'], 3 | data() { 4 | return { 5 | installing: false, 6 | alreadyInstaleld: false, 7 | updateAvailable: false, 8 | currentVersion: null, 9 | fromCloud: null 10 | } 11 | }, 12 | template: ` 13 |
14 |
15 | 16 |
17 |
18 | 19 |

{{fgcData.strings.installed}}

20 | 21 |

{{fgcData.strings.local_block}}

22 | 23 |
24 |

{{fgcData.strings.update_available}}

25 |
26 | 27 | {{fgcData.strings.show_more_details}} 28 | 29 |
30 |

{{ block.name }}

31 | {{fgcData.strings.by}}: 32 | 33 | {{ blockManifest.author.name }} 34 | 35 | 36 | {{ blockManifest.author }} 37 | 38 | 39 | {{fgcData.strings.version}}: {{ currentVersion }} 40 | 41 |
42 | 47 | 52 | {{fgcData.strings.homepage}} 53 |
54 |
55 | 56 |
57 | `, 58 | mounted() { 59 | this.currentVersion = this.block.version 60 | if (!!window.store.state.installedBlocks.filter(b => b.package_name == this.block.packageName).length) { 61 | this.alreadyInstaleld = this.currentBrowseState != 'installed' 62 | if (this.currentBrowseState == 'installed') { 63 | window.store.state.installedBlocks.map(b => { 64 | if (b.package_name == this.block.packageName && !this.isLocalBlock) { 65 | jQuery.get(`https://api.gutenbergcloud.org/blocks/${b.package_name}`, (res) => { 66 | if (res) { 67 | let block = res 68 | const theBlock = {} 69 | theBlock.jsUrl = `https://cdn.jsdelivr.net/npm/${block.name}@${block.version}/${block.config.js}` 70 | theBlock.cssUrl = `https://cdn.jsdelivr.net/npm/${block.name}@${block.version}/${block.config.css}` 71 | theBlock.editorCss = block.config.editor ? `https://cdn.jsdelivr.net/npm/${block.name}@${block.version}/${block.config.editor}` : null 72 | theBlock.infoUrl = `https://www.npmjs.com/package/${block.name}` 73 | theBlock.imageUrl = `https://cdn.jsdelivr.net/npm/${block.name}@${block.version}/${block.config.screenshot}` 74 | theBlock.name = block.config.name 75 | theBlock.blockManifest = JSON.stringify(block.package) 76 | theBlock.version = block.version 77 | theBlock.packageName = block.name 78 | 79 | if (res.version && b.block_version < res.version) { 80 | this.updateAvailable = true 81 | theBlock.availVersion = block.version 82 | } 83 | 84 | this.fromCloud = theBlock 85 | 86 | if (this.updateAvailable) { 87 | this.setAvalVersion() 88 | } 89 | } 90 | }) 91 | } 92 | }) 93 | this.currentVersion = window.store.state.installedBlocks.filter(b => b.package_name == this.block.packageName)[0].block_version 94 | } 95 | } 96 | }, 97 | methods: { 98 | installBlock() { 99 | this.installing = true 100 | let postData = this.block 101 | console.log('Install block', postData) 102 | jQuery.ajax({ 103 | type: 'POST', 104 | url: fgcData.ajaxUrl, 105 | data: { 106 | action: "fgc_install_block", 107 | data: postData 108 | } 109 | }) 110 | .done(res => { 111 | this.installing = false 112 | this.alreadyInstaleld = true 113 | if (!this.isLocalBlock) { 114 | this.incrementInstalls(this.block.packageName) 115 | } 116 | window.store.dispatch('getInstalledBlocks') 117 | window.store.commit('setNotification', { text: `${fgcData.strings.the_block} ${this.block.name} ${fgcData.strings.block_installed}`, class: 'show success' }) 118 | console.log('Block installed ', res.data) 119 | }) 120 | .fail(error => { 121 | this.installing = false 122 | console.log('There is some issues installing block: ', error); 123 | }) 124 | }, 125 | uninstallBlock() { 126 | this.installing = true 127 | let postData = this.block 128 | jQuery.ajax({ 129 | type: 'POST', 130 | url: fgcData.ajaxUrl, 131 | data: { 132 | action: "fgc_uninstall_block", 133 | data: postData 134 | } 135 | }) 136 | .done(res => { 137 | this.installing = false 138 | this.alreadyInstaleld = false 139 | if (!this.isLocalBlock) { 140 | this.decrementInstalls(this.block.packageName) 141 | } 142 | window.store.dispatch('getInstalledBlocks') 143 | window.store.commit('setNotification', { text: `${fgcData.strings.block} ${this.block.name} ${fgcData.strings.block_uninstalled}`, class: 'show success' }) 144 | console.log('Block uninstalled ', res.data) 145 | }) 146 | .fail(error => { 147 | this.installing = false 148 | console.log('There is some issues uninstalling block: ', error) 149 | }) 150 | }, 151 | updateBlock() { 152 | this.installing = true 153 | let postData = this.fromCloud 154 | jQuery.ajax({ 155 | type: 'POST', 156 | url: fgcData.ajaxUrl, 157 | data: { 158 | action: "fgc_update_block", 159 | data: postData 160 | } 161 | }) 162 | .done(res => { 163 | this.installing = false 164 | this.updateAvailable = false 165 | this.currentVersion = this.block.version 166 | window.store.dispatch('getInstalledBlocks') 167 | window.store.commit('setNotification', { text: `${fgcData.strings.block} ${this.block.name} ${fgcData.strings.block_updated}`, class: 'show success' }) 168 | console.log('Block Updated ', res.data) 169 | }) 170 | .fail(error => { 171 | this.installing = false 172 | console.log('There is some issues updating block: ', error) 173 | }) 174 | }, 175 | setAvalVersion() { 176 | let postData = this.fromCloud 177 | jQuery.ajax({ 178 | type: 'POST', 179 | url: fgcData.ajaxUrl, 180 | data: { 181 | action: "fgc_update_version", 182 | data: postData 183 | } 184 | }) 185 | .done(res => { 186 | console.log('Available new version ', res.data) 187 | }) 188 | .fail(error => { 189 | console.log('There is some issues: ', error) 190 | }) 191 | }, 192 | incrementInstalls(packageName) { 193 | jQuery.ajax({ 194 | type: 'POST', 195 | data: { increment: 1 }, 196 | url: `https://api.gutenbergcloud.org/blocks/${packageName}` 197 | }) 198 | .done(() => { 199 | console.log('Installation counter increased ') 200 | }) 201 | .fail(error => { 202 | console.log('Some errors occured white increasing number of installs: ', error) 203 | }) 204 | }, 205 | decrementInstalls(packageName) { 206 | jQuery.ajax({ 207 | type: 'POST', 208 | data: { increment: -1 }, 209 | url: `https://api.gutenbergcloud.org/blocks/${packageName}` 210 | }) 211 | .done(() => { 212 | console.log('Installation counter decreased ') 213 | }) 214 | .fail(error => { 215 | console.log('Some errors occured white increasing number of installs: ', error) 216 | }) 217 | }, 218 | openMoreDetails() { 219 | window.store.commit('openOverlay', this.block) 220 | } 221 | }, 222 | computed: { 223 | currentBrowseState() { 224 | return window.store.state.browseState 225 | }, 226 | blockManifest() { 227 | let manifest = JSON.parse(this.block.blockManifest) 228 | return (typeof manifest == 'string' && manifest != '') ? JSON.parse(manifest) : manifest 229 | }, 230 | isLocalBlock() { 231 | return (this.blockManifest && this.blockManifest.isLocal) || false 232 | }, 233 | blockUrl() { 234 | if (this.blockManifest.homepage) { 235 | return this.blockManifest.homepage 236 | } else if (this.blockManifest.author && typeof this.blockManifest.author == 'object' && this.blockManifest.author.url) { 237 | return this.blockManifest.author.url 238 | } else { 239 | return `https://www.npmjs.com/package/${this.block.packageName}` 240 | } 241 | }, 242 | } 243 | }) 244 | -------------------------------------------------------------------------------- /assets/source/js/block-details.js: -------------------------------------------------------------------------------- 1 | Vue.component('block-details', { 2 | props: ['block'], 3 | data() { 4 | return { 5 | alreadyInstaleld: false, 6 | spinnerLoaded: false 7 | } 8 | }, 9 | template: ` 10 | `, 56 | mounted() { 57 | window.addEventListener('keyup', this.keypressEvent) 58 | if (!!window.store.state.installedBlocks.filter(b => b.package_name == this.block.packageName).length) { 59 | this.alreadyInstaleld = true 60 | } 61 | }, 62 | computed: { 63 | blockManifest() { 64 | let manifest = JSON.parse(this.block.blockManifest) 65 | return (typeof manifest == 'string' && manifest != '') ? JSON.parse(manifest) : manifest 66 | }, 67 | isLocalBlock() { 68 | return (this.blockManifest && this.blockManifest.isLocal) || false 69 | }, 70 | blockUrl() { 71 | if (this.blockManifest.homepage) { 72 | return this.blockManifest.homepage 73 | } else if (this.blockManifest.author && typeof this.blockManifest.author == 'object' && this.blockManifest.author.url) { 74 | return this.blockManifest.author.url 75 | } else { 76 | return `https://www.npmjs.com/package/${this.block.packageName}` 77 | } 78 | }, 79 | authorUrl() { 80 | if (this.blockManifest.author && typeof this.blockManifest.author == 'object' && this.blockManifest.author.url) { 81 | return this.blockManifest.author.url 82 | } else if (this.blockManifest.homepage) { 83 | return this.blockManifest.homepage 84 | } else { 85 | return `https://www.npmjs.com/package/${this.block.packageName}` 86 | } 87 | }, 88 | blockAuthor() { 89 | if (this.blockManifest.author && typeof this.blockManifest.author == 'object' && this.blockManifest.author.name) { 90 | return this.blockManifest.author.name 91 | } else if (this.blockManifest.author && typeof this.blockManifest.author == 'string') { 92 | return this.blockManifest.author 93 | } else { 94 | return null 95 | } 96 | }, 97 | blockTags() { 98 | return this.blockManifest ? this.blockManifest.keywords.join(', ') : '' 99 | } 100 | }, 101 | methods: { 102 | keypressEvent(e) { 103 | if (e.keyCode === 27) { 104 | this.closeOverlay() 105 | } 106 | }, 107 | closeOverlay() { 108 | window.store.commit('openOverlay', null) 109 | }, 110 | installBlock() { 111 | this.spinnerLoaded = true 112 | let postData = this.block 113 | console.log('Install block', postData) 114 | jQuery.ajax({ 115 | type: 'POST', 116 | url: fgcData.ajaxUrl, 117 | data: { 118 | action: "fgc_install_block", 119 | data: postData 120 | } 121 | }) 122 | .done(res => { 123 | this.alreadyInstaleld = true 124 | this.spinnerLoaded = false 125 | if (!this.isLocalBlock) { 126 | this.incrementInstalls(this.block.packageName) 127 | } 128 | window.store.dispatch('getInstalledBlocks') 129 | window.store.commit('setNotification', { text: `${fgcData.strings.the_block} ${this.block.name} ${fgcData.strings.block_installed}`, class: 'show success' }) 130 | console.log('Block installed ', res.data) 131 | }) 132 | .fail(error => { 133 | this.installing = false 134 | console.log('There is some issues installing block: ', error); 135 | }) 136 | }, 137 | deleteBlock() { 138 | this.spinnerLoaded = true 139 | // First we need to uninstall the block if already installed 140 | if (this.alreadyInstaleld) { 141 | this.uninstallBlock() 142 | } 143 | let postData = { 144 | block: this.block, 145 | nonce: fgcData.ajaxNonce 146 | } 147 | jQuery.ajax({ 148 | type: 'POST', 149 | url: fgcData.ajaxUrl, 150 | data: { 151 | action: "fgc_delete_block", 152 | data: postData 153 | } 154 | }) 155 | .done(res => { 156 | window.store.commit('setNotification', { text: `${fgcData.strings.the_block} ${this.block.name} ${fgcData.strings.block_deleted}`, class: 'show success' }) 157 | window.store.commit('setRefetchBlocks', true) 158 | this.closeOverlay() 159 | this.spinnerLoaded = false 160 | window.store.dispatch('getInstalledBlocks') 161 | console.log('Block removed ', res.data) 162 | }) 163 | .fail(error => { 164 | this.installing = false 165 | console.log('There is some issues installing block: ', error); 166 | }) 167 | }, 168 | uninstallBlock() { 169 | let postData = this.block 170 | jQuery.ajax({ 171 | type: 'POST', 172 | url: fgcData.ajaxUrl, 173 | data: { 174 | action: "fgc_uninstall_block", 175 | data: postData 176 | } 177 | }) 178 | .done(res => { 179 | this.alreadyInstaleld = false 180 | if (!this.isLocalBlock) { 181 | this.decrementInstalls(this.block.packageName) 182 | } 183 | window.store.dispatch('getInstalledBlocks') 184 | window.store.commit('setNotification', { text: `${fgcData.strings.block} ${this.block.name} ${fgcData.strings.block_uninstalled}`, class: 'show success' }) 185 | console.log('Block uninstalled ', res.data) 186 | }) 187 | .fail(error => { 188 | this.installing = false 189 | console.log('There is some issues uninstalling block: ', error) 190 | }) 191 | }, 192 | incrementInstalls(packageName) { 193 | jQuery.ajax({ 194 | type: 'PUT', 195 | url: `https://api.gutenbergcloud.org/blocks/${packageName}` 196 | }) 197 | .done(() => { 198 | console.log('Installation counter increased ') 199 | }) 200 | .fail(error => { 201 | console.log('Some errors occured white increasing number of installs: ', error) 202 | }) 203 | }, 204 | decrementInstalls(packageName) { 205 | jQuery.ajax({ 206 | type: 'DELETE', 207 | url: `https://api.gutenbergcloud.org/blocks/${packageName}` 208 | }) 209 | .done(() => { 210 | console.log('Installation counter decreased ') 211 | }) 212 | .fail(error => { 213 | console.log('Some errors occured white increasing number of installs: ', error) 214 | }) 215 | }, 216 | } 217 | }) -------------------------------------------------------------------------------- /assets/source/js/explorer-filter.js: -------------------------------------------------------------------------------- 1 | Vue.component('explorer-filter', { 2 | componenets: ['filter-drawer'], 3 | data() { 4 | return { 5 | drawerFilterOpen: false, 6 | searchQuery: null, 7 | filterLinks: [ 8 | { 9 | name: fgcData.strings.installed, 10 | slug: 'installed' 11 | }, 12 | { 13 | name: fgcData.strings.popular, 14 | slug: 'popular' 15 | }, 16 | { 17 | name: fgcData.strings.latest, 18 | slug: 'latest' 19 | }, 20 | { 21 | name: fgcData.strings.local, 22 | slug: 'local' 23 | } 24 | ] 25 | } 26 | }, 27 | template: ` 28 |
29 |
30 | {{ blocksCount }} 31 |
32 | 33 | 36 | 37 | 38 | 39 |
40 | 41 | 42 |
43 | `, 44 | mounted() { 45 | if (!window.store.state.installedBlocks.length && window.store.state.browseState != 'local') { 46 | this.filterLink('popular') 47 | } 48 | }, 49 | methods: { 50 | filterLink(newFilter) { 51 | let currentState = window.location.search.replace(/\&browse[=a-z]*/, '') 52 | history.pushState({state: newFilter}, null, `${currentState}&browse=${newFilter}`) 53 | window.store.commit('setBrowseState', newFilter) 54 | }, 55 | currentFilter(filter) { 56 | return window.store.state.browseState == filter ? 'current' : '' 57 | }, 58 | searchForBlock() { 59 | let currentState = window.location.search.replace(/\&q[=a-z\-]*/, '') 60 | let query = this.searchQuery.replace(/\s+/g, '-').toLowerCase() 61 | history.pushState({state: query}, null, `${currentState}&q=${query}`) 62 | window.store.commit('setSearchQuery', query) 63 | } 64 | }, 65 | computed: { 66 | blocksCount() { 67 | if (window.store.state.browseState === 'installed') { 68 | return window.store.state.installedBlocks.length 69 | } else { 70 | return window.store.state.blocksCount 71 | } 72 | } 73 | } 74 | }) 75 | 76 | 77 | Vue.component('filter-drawer', { 78 | template: ` 79 |
80 |
81 | 82 | 83 |
84 |
85 | Subject 86 |
87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
96 |
97 |
98 | Features 99 |
100 | 101 | 102 | 103 | 104 | 105 | 106 |
107 |
108 |
109 | Layout 110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 |
120 |
121 |
122 | 123 | 124 |
125 | 126 |
127 | ` 128 | }) 129 | -------------------------------------------------------------------------------- /assets/source/js/script.js: -------------------------------------------------------------------------------- 1 | var store = new Vuex.Store({ 2 | state: { 3 | notification: {}, 4 | browseState: null, 5 | installedBlocks: fgcData.installedBlocks, 6 | searchQuery: null, 7 | opendOverlay: null, 8 | blocksCount: 0, 9 | refetchBlocks: false 10 | }, 11 | mutations: { 12 | setNotification(state, payload) { 13 | state.notification = payload 14 | }, 15 | setBrowseState(state, payload) { 16 | state.browseState = payload 17 | }, 18 | setInstalledBlocks(state, payload) { 19 | state.installedBlocks = payload 20 | }, 21 | setSearchQuery(state, payload) { 22 | state.searchQuery = payload 23 | }, 24 | openOverlay(state, payload) { 25 | state.opendOverlay = payload 26 | }, 27 | setBlocksCount(state, payload) { 28 | state.blocksCount = payload 29 | }, 30 | setRefetchBlocks(state, payload) { 31 | state.refetchBlocks = payload 32 | } 33 | }, 34 | actions: { 35 | getInstalledBlocks(store) { 36 | jQuery.ajax({ 37 | type: 'GET', 38 | url: fgcData.ajaxUrl, 39 | data: { 40 | action: "fgc_get_all_blocks" 41 | } 42 | }) 43 | .done(res => { 44 | store.commit('setInstalledBlocks', res.data) 45 | }) 46 | .fail(error => { 47 | console.log('There is some issues installing block: ', error); 48 | }) 49 | } 50 | } 51 | }) 52 | 53 | 54 | var app = new Vue({ 55 | el: '#blockExplorer', 56 | data() { 57 | return { 58 | blocks: [] 59 | } 60 | }, 61 | created() { 62 | window.store.dispatch('getInstalledBlocks') 63 | const currentBrowseState = this.getUrlParams('browse') ? this.getUrlParams('browse') : 'installed' 64 | const q = this.getUrlParams('q') ? this.getUrlParams('q') : '' 65 | let query = { 66 | state: currentBrowseState, 67 | q 68 | } 69 | this.getBlocks(query) 70 | window.store.commit('setBrowseState', currentBrowseState) 71 | }, 72 | mounted() { 73 | window.addEventListener('popstate', this.fetchBlocks) 74 | }, 75 | watch: { 76 | currentBrowseFilter(newState) { 77 | const q = this.getUrlParams('q') ? this.getUrlParams('q') : '' 78 | window.store.dispatch('getInstalledBlocks') 79 | let query = { 80 | state: newState, 81 | q 82 | } 83 | this.getBlocks(query) 84 | }, 85 | currentSearchQuery(q) { 86 | const currentBrowseState = this.getUrlParams('browse') ? this.getUrlParams('browse') : 'installed' 87 | window.store.dispatch('getInstalledBlocks') 88 | let query = { 89 | state: currentBrowseState, 90 | q 91 | } 92 | this.getBlocks(query) 93 | }, 94 | installedBlocks(newBlocksList, oldBlocksList) { 95 | const currentBrowseState = this.getUrlParams('browse') ? this.getUrlParams('browse') : 'installed' 96 | if (newBlocksList.length != oldBlocksList.length && currentBrowseState == 'installed') { 97 | this.blocks = this.blocks.filter(block => newBlocksList.some(bl => bl.package_name == block.packageName)) 98 | } 99 | }, 100 | refetchBlocks() { 101 | const currentBrowseState = this.getUrlParams('browse') ? this.getUrlParams('browse') : 'installed' 102 | let query = { 103 | state: currentBrowseState 104 | } 105 | this.getBlocks(query) 106 | } 107 | }, 108 | methods: { 109 | fetchBlocks(e) { 110 | let state = null 111 | if (e.state) { 112 | state = e.state.state 113 | } 114 | this.getBlocks(state) 115 | }, 116 | getBlocks(query) { 117 | let blocks = [] 118 | let queryString = '' 119 | if (query.q && query.q !== null) { 120 | queryString = `q=${query.q}` 121 | } 122 | if (query.state !== null) { 123 | queryString += `&order=${query.state}` 124 | } 125 | if (query.state == null || query.state == 'installed') { 126 | if (this.installedBlocks.length) { 127 | for (const block of this.installedBlocks) { 128 | const theBlock = {} 129 | theBlock.jsUrl = block.js_url 130 | theBlock.cssUrl = block.css_url 131 | theBlock.editorCss = block.editor_css 132 | theBlock.infoUrl = block.info_url 133 | theBlock.imageUrl = block.thumbnail 134 | theBlock.name = block.block_name 135 | theBlock.blockManifest = '\"' + block.block_manifest + '\"' 136 | theBlock.version = block.block_version 137 | theBlock.packageName = block.package_name 138 | 139 | if ((query.q && query.q !== null && (theBlock.name.toLowerCase().indexOf(query.q.toLowerCase()) > -1 || theBlock.packageName.toLowerCase().indexOf(query.q.toLowerCase()) > -1)) || !query.q ) { 140 | blocks.push(theBlock) 141 | } 142 | } 143 | } 144 | } else if (query.state == 'local') { 145 | this.localBlocks(query) 146 | } else { 147 | jQuery.get(`https://api.gutenbergcloud.org/blocks?${queryString}`, (res) => { 148 | if (res.count) { 149 | window.store.commit('setBlocksCount', res.count) 150 | } 151 | for (const block of res.rows) { 152 | const theBlock = {} 153 | theBlock.jsUrl = `https://cdn.jsdelivr.net/npm/${block.name}@${block.version}/${block.config.js}` 154 | theBlock.cssUrl = `https://cdn.jsdelivr.net/npm/${block.name}@${block.version}/${block.config.css}` 155 | theBlock.editorCss = block.config.editor ? `https://cdn.jsdelivr.net/npm/${block.name}@${block.version}/${block.config.editor}` : null 156 | theBlock.infoUrl = `https://www.npmjs.com/package/${block.name}` 157 | theBlock.imageUrl = `https://cdn.jsdelivr.net/npm/${block.name}@${block.version}/${block.config.screenshot}` 158 | theBlock.name = block.config.name 159 | theBlock.blockManifest = JSON.stringify(block.package) 160 | theBlock.version = block.version 161 | theBlock.packageName = block.name 162 | if (query.state == null || query.state == 'installed') { 163 | if (this.installedBlocks.length && this.installedBlocks.filter(b => b.package_name == theBlock.packageName).length) { 164 | blocks.push(theBlock) 165 | } 166 | } else { 167 | blocks.push(theBlock) 168 | } 169 | } 170 | }) 171 | } 172 | this.blocks = blocks 173 | }, 174 | getUrlParams(name, url) { 175 | if (!url) url = window.location.href 176 | name = name.replace(/[\[\]]/g, '\\$&') 177 | let regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)') 178 | let results = regex.exec(url) 179 | if (!results) return null 180 | if (!results[2]) return '' 181 | return decodeURIComponent(results[2].replace(/\+/g, ' ')) 182 | }, 183 | showUploader() { 184 | document.body.classList.toggle('show-upload-view') 185 | }, 186 | localBlocks(query) { 187 | jQuery.ajax({ 188 | type: 'POST', 189 | url: fgcData.ajaxUrl, 190 | data: { 191 | action: "fgc_local_blocks" 192 | } 193 | }) 194 | .done(res => { 195 | if (res.data.length) { 196 | window.store.commit('setBlocksCount', res.data.length) 197 | window.store.commit('setRefetchBlocks', false) 198 | } else { 199 | window.store.commit('setBlocksCount', 0) 200 | } 201 | if (query.q && query.q !== null) { 202 | this.blocks = res.data.filter(block => block.name.toLowerCase().indexOf(query.q.toLowerCase()) > -1 || block.packageName.toLowerCase().indexOf(query.q.toLowerCase()) > -1) 203 | } else { 204 | this.blocks = res.data 205 | } 206 | }) 207 | .fail(error => { 208 | console.log('There is some issues getting local blocks: ', error); 209 | }) 210 | }, 211 | }, 212 | computed: { 213 | currentBrowseFilter() { 214 | return window.store.state.browseState 215 | }, 216 | currentSearchQuery() { 217 | return window.store.state.searchQuery 218 | }, 219 | installedBlocks() { 220 | return window.store.state.installedBlocks 221 | }, 222 | openOverlay() { 223 | return window.store.state.opendOverlay 224 | }, 225 | refetchBlocks() { 226 | return window.store.state.refetchBlocks 227 | } 228 | } 229 | }) 230 | -------------------------------------------------------------------------------- /assets/source/scss/style.css: -------------------------------------------------------------------------------- 1 | [v-cloak] > * { 2 | display: none; } 3 | 4 | .g-blocks-filter { 5 | padding-left: 20px; } 6 | 7 | .block-version, 8 | .block-author { 9 | position: absolute; 10 | top: 15px; 11 | right: 20px; } 12 | 13 | .spinner.installing-block { 14 | visibility: inherit; 15 | position: absolute; 16 | top: 50%; 17 | left: 50%; 18 | transform: translate(-50%, -50%); } 19 | 20 | .install-block-btn.button-delete { 21 | color: #fff; 22 | border-color: #E91E63; 23 | background: #E91E63; 24 | box-shadow: 0 1px 0 #E91E63; 25 | vertical-align: top; } 26 | .install-block-btn.button-delete:hover { 27 | color: #fff; 28 | border-color: #ab194a; 29 | background: #c22057; 30 | box-shadow: 0 1px 0 #cc1a56; 31 | vertical-align: top; } 32 | 33 | .fgc-notification { 34 | visibility: hidden; 35 | min-width: 300px; 36 | background-color: #333; 37 | color: #fff; 38 | text-align: center; 39 | border-radius: 2px; 40 | padding: 10px 24px; 41 | position: fixed; 42 | z-index: 100000; 43 | left: 50%; 44 | transform: translateX(-50%); 45 | bottom: 30px; } 46 | 47 | .fgc-notification.success { 48 | background-color: #1883db; } 49 | 50 | .fgc-notification.error { 51 | background-color: #d1554c; } 52 | 53 | .fgc-notification.show { 54 | visibility: visible; 55 | animation: fadein 0.5s, fadeout 0.5s 3.5s; } 56 | 57 | @keyframes fadein { 58 | from { 59 | bottom: 0; 60 | opacity: 0; } 61 | to { 62 | bottom: 30px; 63 | opacity: 1; } } 64 | 65 | @keyframes fadeout { 66 | from { 67 | bottom: 30px; 68 | opacity: 1; } 69 | to { 70 | bottom: 0; 71 | opacity: 0; } } 72 | 73 | .fgc-wrapper-grid { 74 | margin-left: 8px; 75 | margin-right: 8px; 76 | margin-top: 10px; } 77 | .fgc-wrapper-grid .postbox { 78 | float: left; 79 | clear: left; 80 | width: 50%; 81 | margin: 0 0 16px; } 82 | @media only screen and (max-width: 850px) { 83 | .fgc-wrapper-grid .postbox { 84 | margin-left: 0 !important; 85 | margin-right: 0 !important; 86 | width: 100%; } } 87 | .fgc-wrapper-grid .postbox .inside { 88 | margin-bottom: 0; } 89 | .fgc-wrapper-grid .postbox:nth-child(odd) { 90 | margin-left: -8px; } 91 | .fgc-wrapper-grid .postbox:nth-child(even) { 92 | float: right; 93 | clear: right; 94 | margin-right: -8px; } 95 | .fgc-wrapper-grid .hndle { 96 | font-size: 14px; 97 | padding: 8px 12px; 98 | margin: 0; 99 | line-height: 1.4; } 100 | .fgc-wrapper-grid .fgc-fields { 101 | border: #ebebeb solid 1px; 102 | background: #fafafa; 103 | border-radius: 3px; } 104 | 105 | .fgc-center-text { 106 | text-align: center; } 107 | 108 | .upload-custom-block .block-install-help code { 109 | font-size: 12px; } 110 | -------------------------------------------------------------------------------- /assets/source/scss/style.scss: -------------------------------------------------------------------------------- 1 | [v-cloak] > * { display:none } 2 | 3 | .g-blocks-filter { 4 | padding-left: 20px; 5 | } 6 | 7 | .block-version, 8 | .block-author { 9 | position: absolute; 10 | top: 15px; 11 | right: 20px; 12 | } 13 | 14 | .spinner.installing-block { 15 | visibility: inherit; 16 | position: absolute; 17 | top: 50%; 18 | left: 50%; 19 | transform: translate(-50%, -50%); 20 | } 21 | 22 | .install-block-btn.button-delete { 23 | color: #fff; 24 | border-color: #E91E63; 25 | background: #E91E63; 26 | box-shadow: 0 1px 0 #E91E63; 27 | vertical-align: top; 28 | 29 | &:hover { 30 | color: #fff; 31 | border-color: #ab194a; 32 | background: #c22057; 33 | box-shadow: 0 1px 0 #cc1a56; 34 | vertical-align: top; 35 | } 36 | } 37 | 38 | .fgc-notification { 39 | visibility: hidden; 40 | min-width: 300px; 41 | background-color: #333; 42 | color: #fff; 43 | text-align: center; 44 | border-radius: 2px; 45 | padding: 10px 24px; 46 | position: fixed; 47 | z-index: 100000; 48 | left: 50%; 49 | transform: translateX(-50%); 50 | bottom: 30px; 51 | } 52 | 53 | .fgc-notification.success{ 54 | background-color: rgb(24, 131, 219); 55 | } 56 | 57 | .fgc-notification.error{ 58 | background-color: #d1554c; 59 | } 60 | 61 | .fgc-notification.show { 62 | visibility: visible; 63 | animation: fadein 0.5s, fadeout 0.5s 3.5s; 64 | } 65 | 66 | @keyframes fadein { 67 | from {bottom: 0; opacity: 0;} 68 | to {bottom: 30px; opacity: 1;} 69 | } 70 | 71 | @keyframes fadeout { 72 | from {bottom: 30px; opacity: 1;} 73 | to {bottom: 0; opacity: 0;} 74 | } 75 | 76 | .fgc-wrapper-grid { 77 | margin-left: 8px; 78 | margin-right: 8px; 79 | margin-top: 10px; 80 | 81 | .postbox { 82 | float: left; 83 | clear: left; 84 | width: 50%; 85 | margin: 0 0 16px; 86 | 87 | @media only screen and (max-width: 850px) { 88 | margin-left: 0 !important; 89 | margin-right: 0 !important; 90 | width: 100%; 91 | } 92 | 93 | .inside { 94 | margin-bottom: 0; 95 | } 96 | } 97 | 98 | .postbox:nth-child(odd) { 99 | margin-left: -8px; 100 | } 101 | 102 | .postbox:nth-child(even) { 103 | float: right; 104 | clear: right; 105 | margin-right: -8px; 106 | } 107 | 108 | .hndle { 109 | font-size: 14px; 110 | padding: 8px 12px; 111 | margin: 0; 112 | line-height: 1.4; 113 | } 114 | 115 | .fgc-fields { 116 | border: #ebebeb solid 1px; 117 | background: #fafafa; 118 | border-radius: 3px; 119 | } 120 | } 121 | 122 | .fgc-center-text { 123 | text-align: center; 124 | } 125 | 126 | .upload-custom-block { 127 | .block-install-help { 128 | code { 129 | font-size: 12px; 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /assets/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/assets/thumbnail.png -------------------------------------------------------------------------------- /cloud-blocks.php: -------------------------------------------------------------------------------- 1 | =5.3" 25 | }, 26 | "type": "library", 27 | "autoload": { 28 | "psr-4": { 29 | "SevenFields\\": "src/" 30 | } 31 | }, 32 | "notification-url": "https://packagist.org/downloads/", 33 | "license": [ 34 | "GPL-2.0" 35 | ], 36 | "authors": [ 37 | { 38 | "name": "Foad Yousefi", 39 | "email": "foadyousefi@gmail.com", 40 | "homepage": "https://7km.co/" 41 | } 42 | ], 43 | "description": "WordPress developer-friendly option pages with custom fields.", 44 | "homepage": "https://7km.co/", 45 | "time": "2018-10-02T07:34:15+00:00" 46 | } 47 | ], 48 | "packages-dev": [], 49 | "aliases": [], 50 | "minimum-stability": "dev", 51 | "stability-flags": { 52 | "foadyousefi/seven-fields": 20 53 | }, 54 | "prefer-stable": false, 55 | "prefer-lowest": false, 56 | "platform": [], 57 | "platform-dev": [] 58 | } 59 | -------------------------------------------------------------------------------- /core/Activator.php: -------------------------------------------------------------------------------- 1 | get_charset_collate(); 41 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 42 | 43 | $sql = "CREATE TABLE $table_name ( 44 | id mediumint(9) NOT NULL AUTO_INCREMENT, 45 | block_name varchar(150) NOT NULL, 46 | package_name varchar(150) NOT NULL UNIQUE, 47 | js_url varchar(255) DEFAULT '' NOT NULL, 48 | css_url varchar(255) DEFAULT '' NOT NULL, 49 | editor_css varchar(255) DEFAULT '', 50 | info_url varchar(255) DEFAULT '' NOT NULL, 51 | thumbnail varchar(255) DEFAULT '' NOT NULL, 52 | block_version varchar(10) DEFAULT '' NOT NULL, 53 | block_manifest text DEFAULT '' NOT NULL, 54 | block_installed datetime DEFAULT CURRENT_TIMESTAMP, 55 | block_updated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 56 | available_version varchar(10) DEFAULT '' NOT NULL, 57 | PRIMARY KEY (id) 58 | ) $charset_collate;"; 59 | 60 | require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 61 | dbDelta( $sql ); 62 | 63 | update_option( 'gutenberg_cloud_db_version', '1.0' ); 64 | } 65 | 66 | 67 | /** 68 | * Update database. 69 | * @since 1.0.0 70 | * @param 71 | * @return 72 | */ 73 | public static function update_db() { 74 | // First we check if there is new version available 75 | $installed_ver = get_option( 'gutenberg_cloud_db_version' ); 76 | if ( $installed_ver != self::$current_db_version ) { 77 | global $wpdb; 78 | $charset_collate = $wpdb->get_charset_collate(); 79 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 80 | 81 | $sql = "CREATE TABLE $table_name ( 82 | id mediumint(9) NOT NULL AUTO_INCREMENT, 83 | block_name varchar(150) NOT NULL, 84 | package_name varchar(150) NOT NULL UNIQUE, 85 | js_url varchar(255) DEFAULT '' NOT NULL, 86 | css_url varchar(255) DEFAULT '' NOT NULL, 87 | editor_css varchar(255) DEFAULT '', 88 | info_url varchar(255) DEFAULT '' NOT NULL, 89 | thumbnail varchar(255) DEFAULT '' NOT NULL, 90 | block_version varchar(10) DEFAULT '' NOT NULL, 91 | block_manifest text DEFAULT '' NOT NULL, 92 | block_installed datetime, 93 | block_updated datetime ON UPDATE CURRENT_TIMESTAMP, 94 | available_version varchar(10) DEFAULT '' NOT NULL, 95 | PRIMARY KEY (id) 96 | ) $charset_collate;"; 97 | 98 | require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 99 | dbDelta( $sql ); 100 | 101 | update_option( 'gutenberg_cloud_db_version', self::$current_db_version ); 102 | } 103 | 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /core/Blocks/Explore.php: -------------------------------------------------------------------------------- 1 | %s installed successfully. You must activate it in local tab.', 'cloud-blocks'), $name[0] ), 'success' ); 80 | } 81 | } else { 82 | \CloudBlocks\Settings\Tools::add_notice( __( 'There was a problem with the upload. Please try again.', 'cloud-blocks' ), 'error' ); 83 | } 84 | } 85 | } 86 | } 87 | 88 | /** 89 | * Add options menu page. 90 | * 91 | * @since 1.0.0 92 | * @param 93 | * @return 94 | */ 95 | public static function add_menu() { 96 | 97 | $update_count = self::count_updates(); 98 | $menu_label = sprintf( esc_html__( self::$page_title, 'cloud-blocks' ) . " %s", "" . number_format_i18n($update_count) . "" ); 99 | 100 | add_menu_page( 101 | esc_html__( self::$page_title, 'cloud-blocks' ), 102 | $menu_label, 103 | 'manage_options', 104 | self::$menu_slug, 105 | array( __class__, 'cloud_explorer' ), 106 | 'dashicons-cloud', 107 | 11 108 | ); 109 | } 110 | 111 | /** 112 | * Settings page output. 113 | * 114 | * @since 1.0.0 115 | * @param 116 | * @return 117 | */ 118 | public static function cloud_explorer() { 119 | ?> 120 |
121 |

122 | 123 | 124 | 125 |
126 | 127 |
128 |
129 |

130 |

131 | %s', 'cloud-blocks' ), '/wp-content/uploads/gutenberg-blocks/*' ); ?> 132 |
133 | 134 |

135 |
136 | 137 | 138 | 139 | 140 | 141 |
142 |
143 |
144 | 145 | 146 | 147 | 148 |
149 |
150 | 151 |
152 | 153 |
154 | 155 |
156 | block_manifest ), true ); 173 | 174 | if( empty($manifest['isLocal']) && !empty($block->available_version) && version_compare($block->available_version, $block->block_version, '>')) { 175 | $counter++; 176 | } 177 | } 178 | 179 | return $counter; 180 | } 181 | 182 | /** 183 | * CRON schedule. 184 | * 185 | * @since 1.1.4 186 | * @param 187 | * @return 188 | */ 189 | public static function cron_schedule() { 190 | if ( !wp_next_scheduled( 'fgc_cron_check_updates' ) ) { 191 | wp_schedule_event(time(), 'daily', 'fgc_cron_check_updates'); 192 | } 193 | } 194 | 195 | /** 196 | * CRON unschedule. 197 | * 198 | * @since 1.1.4 199 | * @param 200 | * @return 201 | */ 202 | public static function cron_unschedule() { 203 | wp_clear_scheduled_hook('fgc_cron_check_updates'); 204 | } 205 | 206 | /** 207 | * CRON schedule. 208 | * 209 | * @since 1.1.4 210 | * @param 211 | * @return 212 | */ 213 | public static function check_updates() { 214 | $installed_blocks = Options::get_all(); 215 | 216 | foreach ( $installed_blocks as $block ) { 217 | // We must check if block is not local block, then we check for new version availability 218 | $manifest = json_decode( stripslashes( $block->block_manifest ), true ); 219 | if ( empty( $manifest['isLocal'] ) ) { 220 | $args = array( 221 | 'method' => 'GET' 222 | ); 223 | $response = wp_remote_request( 'https://api.gutenbergcloud.org/blocks/' . $block->package_name, $args ); 224 | $body = wp_remote_retrieve_body( $response ); 225 | $the_block = json_decode( $body, true ); 226 | 227 | if( !empty($the_block['version']) && $the_block['version'] !== $block->block_version) { 228 | $_REQUEST['data'] = $the_block; 229 | Blocks::update_version($the_block); 230 | } 231 | } 232 | } 233 | 234 | } 235 | 236 | } 237 | 238 | -------------------------------------------------------------------------------- /core/Blocks/Options.php: -------------------------------------------------------------------------------- 1 | id, $options ); 37 | 38 | return array( 39 | 'message' => 'Block was already installed, and updated with new data.', 40 | 'block_id' => $block->id 41 | ); 42 | } else if ( isset( $block ) ) { 43 | return array( 44 | 'message' => 'Block already installed.', 45 | 'block_id' => $block->id 46 | ); 47 | } else { 48 | // If not exists, so insert it. 49 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 50 | 51 | $id = $wpdb->insert( 52 | $table_name, 53 | array( 54 | 'block_name' => $block_name, 55 | 'package_name' => $package_name, 56 | 'js_url' => $js_url, 57 | 'css_url' => $css_url, 58 | 'editor_css' => $editor_css, 59 | 'info_url' => $info_url, 60 | 'thumbnail' => $thumbnail, 61 | 'block_version' => $block_version, 62 | 'block_manifest' => $block_manifest 63 | ) 64 | ); 65 | return array( 66 | 'message' => 'Block installed', 67 | 'block_id' => $id 68 | ); 69 | } 70 | } 71 | 72 | /** 73 | * Insert block into database. 74 | * @since 1.0.0 75 | * @param array $block The array of block values 76 | * @return int $id Inserted records id 77 | */ 78 | public static function insert( $block ) { 79 | global $wpdb; 80 | // Validate block 81 | $block_name = isset( $block['block_name'] ) ? $block['block_name'] : ''; 82 | $package_name = isset( $block['package_name'] ) ? $block['package_name'] : ''; 83 | $js_url = isset( $block['js_url'] ) ? $block['js_url'] : ''; 84 | $css_url = isset( $block['css_url'] ) ? $block['css_url'] : ''; 85 | $editor_css = isset( $block['editor_css'] ) ? $block['editor_css'] : ''; 86 | $info_url = isset( $block['info_url'] ) ? $block['info_url'] : ''; 87 | $thumbnail = isset( $block['thumbnail'] ) ? $block['thumbnail'] : ''; 88 | $block_version = isset( $block['block_version'] ) ? $block['block_version'] : ''; 89 | $block_manifest = isset( $block['block_manifest'] ) ? $block['block_manifest'] : ''; 90 | 91 | // First of all, lets make sure column exists or not. 92 | $block = self::get( $package_name ); 93 | if ( isset( $block ) ) { 94 | return $block; 95 | } else { 96 | 97 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 98 | 99 | $imserted = $wpdb->insert( 100 | $table_name, 101 | array( 102 | 'block_name' => $block_name, 103 | 'package_name' => $package_name, 104 | 'js_url' => $js_url, 105 | 'css_url' => $css_url, 106 | 'editor_css' => $editor_css, 107 | 'info_url' => $info_url, 108 | 'thumbnail' => $thumbnail, 109 | 'block_version' => $block_version, 110 | 'block_manifest' => $block_manifest 111 | ) 112 | ); 113 | } 114 | 115 | if ( $imserted ) { 116 | return $wpdb->insert_id; 117 | } 118 | 119 | return false; 120 | 121 | } 122 | 123 | /** 124 | * Update existing value in database. 125 | * @since 1.0.0 126 | * @param array $options The options need to be stored into database 127 | * @return int $id Inserted records id 128 | */ 129 | public static function update( $id, $options ) { 130 | global $wpdb; 131 | 132 | $block_name = $options['block_name']; 133 | $package_name = $options['package_name']; 134 | $js_url = $options['js_url']; 135 | $css_url = $options['css_url']; 136 | $editor_css = $options['editor_css']; 137 | $info_url = $options['info_url']; 138 | $thumbnail = $options['thumbnail']; 139 | $block_version = $options['block_version']; 140 | $block_manifest = $options['block_manifest']; 141 | 142 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 143 | 144 | $id = $wpdb->update( 145 | $table_name, 146 | array( 147 | 'block_name' => $block_name, 148 | 'package_name' => $package_name, 149 | 'js_url' => $js_url, 150 | 'css_url' => $css_url, 151 | 'editor_css' => $editor_css, 152 | 'info_url' => $info_url, 153 | 'thumbnail' => $thumbnail, 154 | 'block_version' => $block_version, 155 | 'block_manifest' => $block_manifest, 156 | 'available_version' => '' 157 | ), 158 | array( 159 | 'id' => $id 160 | ) 161 | ); 162 | 163 | return $id; 164 | } 165 | 166 | /** 167 | * Update existing value in database. 168 | * @since 1.1.4 169 | * @param array $options The options need to be stored into database 170 | * @return int $id Inserted records id 171 | */ 172 | public static function update_version( $id, $options ) { 173 | global $wpdb; 174 | 175 | $available_version = $options['available_version']; 176 | 177 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 178 | 179 | $id = $wpdb->update( 180 | $table_name, 181 | array( 182 | 'available_version' => $available_version 183 | ), 184 | array( 185 | 'id' => $id 186 | ) 187 | ); 188 | 189 | return $id; 190 | } 191 | 192 | /** 193 | * Get all installed blocks. 194 | * @since 1.0.0 195 | * @param 196 | * @return object|null $blocks All installed blocks 197 | */ 198 | public static function get_all() { 199 | global $wpdb; 200 | 201 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 202 | $blocks = $wpdb->get_results( "SELECT * FROM $table_name" ); 203 | 204 | return $blocks; 205 | } 206 | 207 | /** 208 | * Read a row from database. 209 | * @since 1.0.0 210 | * @param string|null $package_name npm package name 211 | * @return object|null $block The block in the database 212 | */ 213 | public static function get( $package_name = null ) { 214 | global $wpdb; 215 | 216 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 217 | $block = $wpdb->get_row( "SELECT * FROM $table_name WHERE package_name = '{$package_name}'" ); 218 | 219 | return $block; 220 | } 221 | 222 | /** 223 | * Delete a row from database. 224 | * @since 1.0.0 225 | * @param string|null $package_name npm package name 226 | * @return object|null $block The block in the database 227 | */ 228 | public static function delete( $package_name = null ) { 229 | global $wpdb; 230 | 231 | $table_name = $wpdb->prefix . str_replace( '-', '_', FGC_NAME ); 232 | $block = $wpdb->delete( $table_name, array('package_name' => $package_name) ); 233 | 234 | return $block; 235 | } 236 | 237 | /** 238 | * Increase number of installs on api.gutenbergcloud.org 239 | * @since 1.0.0 240 | * @param string|null $package_name npm package name 241 | * @return object|null $body Request response 242 | */ 243 | public static function increase_installs( $package_name = null ) { 244 | if ( empty( $package_name ) ) { 245 | return; 246 | } 247 | $args = array( 248 | 'method' => 'PUT' 249 | ); 250 | $response = wp_remote_request( 'https://api.gutenbergcloud.org/blocks/' . $package_name, $args ); 251 | $body = wp_remote_retrieve_body( $response ); 252 | return $body; 253 | } 254 | 255 | } 256 | -------------------------------------------------------------------------------- /core/CloudBlocks.php: -------------------------------------------------------------------------------- 1 | = 5 ) { 25 | $this->init(); 26 | } else { 27 | add_action( 'admin_notices', array( $this, 'gutenberg_inactive_notice' ) ); 28 | } 29 | } 30 | 31 | /** 32 | * Show admin notice if Gutenberg is not active. 33 | * @since 1.0.0 34 | * @param 35 | * @return 36 | */ 37 | public function gutenberg_inactive_notice() { 38 | ?> 39 |
40 |

41 | 42 | 43 | 44 |

45 |
46 | admin_url( 'admin-ajax.php' ), 87 | 'installedBlocks' => Options::get_all(), 88 | 'strings' => Translations::strings(), 89 | 'ajaxNonce' => wp_create_nonce('fgc_ajax_nonce'), 90 | 'defaultThumbnail'=> FGC_URL. 'assets/thumbnail.png', 91 | ); 92 | wp_localize_script( 'gutenberg_cloud_admin_js', 'fgcData', $localized_data ); 93 | wp_enqueue_style( 'gutenberg_cloud_admin_styles', FGC_URL . 'assets/css/style.css', false, FGC_VERSION ); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /core/Settings/Tools.php: -------------------------------------------------------------------------------- 1 | block_name ) ) { 106 | self::add_notice( sprintf(__('Block %s already installed.', 'gutenberg-cloug'), $imported->block_name ), 'error' ); 107 | } else { 108 | Options::increase_installs( $block['package_name'] ); 109 | self::add_notice( sprintf(__('Block %s installed successfully.', 'gutenberg-cloug'), $block['block_name'] ), 'success' ); 110 | } 111 | } else { 112 | self::add_notice( sprintf(__('Incorrect file type', 'gutenberg-cloug'), $block['block_name'] ), 'success' ); 113 | } 114 | } 115 | 116 | } 117 | 118 | } 119 | } 120 | 121 | /** 122 | * Encode json object to be exported. 123 | * 124 | * @since 1.0.0 125 | * @param object|array $json Array or object to be encoded 126 | * @return 127 | */ 128 | private static function fgc_json_encode( $json ) { 129 | 130 | // PHP at least 5.4 131 | if( version_compare(PHP_VERSION, '5.4.0', '>=') ) { 132 | return json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); 133 | } 134 | 135 | // PHP less than 5.4 136 | $json = json_encode($json); 137 | 138 | // http://snipplr.com/view.php?codeview&id=60559 139 | $result = ''; 140 | $pos = 0; 141 | $strLen = strlen($json); 142 | $indentStr = " "; 143 | $newLine = "\n"; 144 | $prevChar = ''; 145 | $outOfQuotes = true; 146 | 147 | for ($i=0; $i<=$strLen; $i++) { 148 | // Grab the next character in the string. 149 | $char = substr($json, $i, 1); 150 | // Are we inside a quoted string? 151 | if ($char == '"' && $prevChar != '\\') { 152 | $outOfQuotes = !$outOfQuotes; 153 | // If this character is the end of an element, 154 | // output a new line and indent the next line. 155 | } else if(($char == '}' || $char == ']') && $outOfQuotes) { 156 | $result .= $newLine; 157 | $pos --; 158 | for ($j=0; $j<$pos; $j++) { 159 | $result .= $indentStr; 160 | } 161 | } 162 | // Add the character to the result string. 163 | $result .= $char; 164 | 165 | // If this character is ':' adda space after it 166 | if($char == ':' && $outOfQuotes) { 167 | $result .= ' '; 168 | } 169 | // If the last character was the beginning of an element, 170 | // output a new line and indent the next line. 171 | if (($char == ',' || $char == '{' || $char == '[') && $outOfQuotes) { 172 | $result .= $newLine; 173 | if ($char == '{' || $char == '[') { 174 | $pos ++; 175 | } 176 | for ($j = 0; $j < $pos; $j++) { 177 | $result .= $indentStr; 178 | } 179 | } 180 | $prevChar = $char; 181 | } 182 | // return 183 | return $result; 184 | } 185 | 186 | /** 187 | * Add settings sub-menu page. 188 | * 189 | * @since 1.0.0 190 | * @param 191 | * @return 192 | */ 193 | public static function settings_page() { 194 | Container::make( __( 'Tools', 'cloud-blocks' ), 'gutenberg-cloud-tools') 195 | ->set_parent( self::$menu_slug ) 196 | ->plain_page() 197 | ->add_fields(array( __CLASS__, 'settings_page_output') ); 198 | } 199 | 200 | /** 201 | * Plugin settings page output. 202 | * 203 | * @since 1.0.0 204 | * @param 205 | * @return 206 | */ 207 | public static function settings_page_output() { 208 | Fields::add('header', null, __( 'Gutenberg cloud configurations', 'cloud-blocks' )); 209 | Fields::add('html', 'export_installed_blocks', null, self::export_fields_html() ); 210 | } 211 | 212 | public static function export_fields_html() { 213 | ?> 214 |
215 | 216 |
217 | 218 |
219 |

220 |
221 |
222 |

223 |

224 | 225 |

226 | 227 |
228 |
229 |
230 | 231 | 232 |
233 |

234 |
235 |
236 |

237 |
238 |
239 |
240 | 241 |
242 |
243 | 246 |
247 |
248 |
249 | 250 |

251 | 252 |

253 | 254 |
255 |
256 |
257 | 258 |
259 |
260 | $text, 276 | 'class' => $class, 277 | 'wrap' => $wrap 278 | ); 279 | } 280 | 281 | 282 | /** 283 | * Add admin notices 284 | * 285 | * @since 1.0.0 286 | * @param string $text 287 | * @param string $class 288 | * @param string $wrap 289 | * @return 290 | */ 291 | public static function get_notices() { 292 | if ( empty( self::$notices ) ) return false; 293 | return self::$notices; 294 | } 295 | 296 | /** 297 | * Admin notices output. 298 | * 299 | * @since 1.0.0 300 | * @param 301 | * @return 302 | */ 303 | public static function admin_notices() { 304 | $notices = self::get_notices(); 305 | if ( !$notices ) return; 306 | // loop 307 | foreach( $notices as $notice ) { 308 | $open = ''; 309 | $close = ''; 310 | // Wrapper tag for admin notice 311 | if ( $notice['wrap'] ) { 312 | $open = "<{$notice['wrap']}>"; 313 | $close = ""; 314 | } 315 | 316 | ?> 317 |
318 | 319 |
320 | __( 'Block', 'cloud-blocks' ), 19 | 'the_block' => __( 'The block', 'cloud-blocks' ), 20 | 'delete' => __( 'Delete', 'cloud-blocks' ), 21 | 'delete_block' => __( 'Delete block', 'cloud-blocks' ), 22 | 'install' => __( 'Install', 'cloud-blocks' ), 23 | 'uninstall' => __( 'Uninstall', 'cloud-blocks' ), 24 | 'local' => __( 'Local', 'cloud-blocks' ), 25 | 'local_block' => __( 'Local block', 'cloud-blocks' ), 26 | 'by' => __( 'By', 'cloud-blocks' ), 27 | 'tags' => __( 'Tags', 'cloud-blocks' ), 28 | 'installed' => __( 'Installed', 'cloud-blocks' ), 29 | 'popular' => __( 'Popular', 'cloud-blocks' ), 30 | 'latest' => __( 'Latest', 'cloud-blocks' ), 31 | 'most_used' => __( 'Most used', 'cloud-blocks' ), 32 | 'search_for_blocks' => __( 'Search for blocks', 'cloud-blocks' ), 33 | 'search_blocks' => __( 'Search blocks...', 'cloud-blocks' ), 34 | 'filter' => __( 'Filter', 'cloud-blocks' ), 35 | 'update_now' => __( 'Update now', 'cloud-blocks' ), 36 | 'show_more_details' => __( 'Show more details', 'cloud-blocks' ), 37 | 'more_details' => __( 'More details', 'cloud-blocks' ), 38 | 'block_installed' => __( 'have been installed successfully.', 'cloud-blocks' ), 39 | 'block_uninstalled' => __( 'have been uninstalled successfully.', 'cloud-blocks' ), 40 | 'block_deleted' => __( 'have been deleted successfully.', 'cloud-blocks' ), 41 | 'block_updated' => __( 'have been updated successfully.', 'cloud-blocks' ), 42 | 'update_available' => __( 'New version available.', 'cloud-blocks' ), 43 | 'version' => __( 'Version', 'cloud-blocks' ), 44 | 'visit_homepage' => __( 'Visit homepage', 'cloud-blocks' ), 45 | 'homepage' => __( 'Homepage', 'cloud-blocks' ), 46 | ); 47 | } 48 | } -------------------------------------------------------------------------------- /core/Uninstall.php: -------------------------------------------------------------------------------- 1 | prefix . str_replace( '-', '_', FGC_NAME ); 35 | $wpdb->query( "DROP TABLE IF EXISTS $table_name" ); 36 | 37 | delete_option("gutenberg_cloud_db_version"); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /docs/changelog.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | #### 1.1.8 4 | * **Fix**: Fix an issue with local blocks directory which was losting every files as block 5 | 6 | #### 1.1.7 7 | * **Fix**: Fix db error in activator hook 8 | * **Change**: Dlete db table on plugin uninstallation 9 | 10 | #### 1.1.6 11 | * **Fix**: Fix missing slash in local blocks 12 | 13 | #### 1.1.5 14 | * **Change**: Replace unpkg.com CDN in favor of jsdelivr.com 15 | 16 | #### 1.1.4 17 | * **Change**: Update counter as a WP CRON (Thanks to [ajotka](https://github.com/front/cloud-blocks/pull/14)) 18 | * **Change**: Update some docs 19 | * **Fix**: Fix polish translations 20 | 21 | #### 1.1.3 22 | * **Fix**: Fix some translations 23 | * **Fix**: Fix database table issue if plugin network activated [issue #13](https://github.com/front/cloud-blocks/issues/13) 24 | * **Cleanup**: Remove custom_blocks method since its not used anymore. This method was for scanning local blocks inside /wp-content/gutenberg-blocks directory 25 | 26 | #### 1.1.2 27 | * **Fix**: Fix wrong label in block details [issue #9](https://github.com/front/cloud-blocks/issues/9) 28 | * **Fix**: Fix network activation issue [issue #11](https://github.com/front/cloud-blocks/issues/11) 29 | * **Add**: Polish translation. (Thanks to [ajotka](https://github.com/front/cloud-blocks/pull/8)) 30 | * **Add**: Update counter & label in menu. (Thanks to [ajotka](https://github.com/front/cloud-blocks/pull/10)) 31 | 32 | 33 | #### 1.1.1 34 | * **Fix**: Update blocks if new version available on the cloud 35 | * **Enhancement**: Improvement in local block screenshots. The filename can be both screenshot or thumbnail and it could be in blocks root directory or build folder 36 | 37 | #### 1.1.0 38 | * **Fix**: Change array dereferencing in activation hook 39 | * **Fix**: Show block in installed list even after block removed from Gutenberg Cloud 40 | * **Fix**: Don't display Installed notice on blocks in Installed tab 41 | * **Fix**: Search blocks in installed and local blocks 42 | * **Add**: Listing for local custom blocks, install and delete them. (In previous versions, blocks were activated automatically, from now on, you need to explicitly activate/deactivate them in the `Local` tab.) 43 | * **Add**: Default block screenshot 44 | * **Change**: Change minimum required php version 45 | * **Change**: Check for db structure update in upgrader_process_complete hook instead of init 46 | 47 | #### 1.0.10 48 | * **Fix**: Fix block js dependency introduced in Gutenberg 4.5.1 49 | 50 | #### 1.0.9 51 | * **Change**: Change increase and decrease number of installations of a block 52 | 53 | #### 1.0.8 54 | * **Fix**: Fix some issues in previous version release 55 | 56 | #### 1.0.7 57 | * **Change:** Private custom blocks now should be under **wp-content/uploads/gutenberg-blocks/**. 58 | * **Add:** Implement UI to upload zip file with custom block [issue #3](https://github.com/front/cloud-blocks/issues/3) 59 | * **Fix:** Fix a bug about enqueue custom blocks assets [issue #4](https://github.com/front/cloud-blocks/issues/4) 60 | * **Fix:** Fix an issue with javascript if search query is empty 61 | 62 | #### 1.0.6 63 | * **Add:** Implement order for blocks (Latest or Popular) 64 | * **Fix:** Block counter in popular and latest tabls 65 | * **Fix:** Display block author 66 | * **Change**: Blocks homepage url 67 | * **Change:** If there is no installed blocks, redirect to Popular tab instead of Installed 68 | * **Change:** Update documentations 69 | 70 | #### 1.0.5 71 | * **Add**: Add modal with block info (like themes) [issue #2](https://github.com/front/cloud-blocks/issues/2) 72 | * **Fix**: Limit enqueue of block styles only to editor or front-end 73 | 74 | #### 1.0.4 75 | * **Fix**: Fix translations variable name in javascript files 76 | * **Change**: Update readme 77 | 78 | #### 1.0.3 79 | * **Change**: Update readme 80 | * **Add**: More docs 81 | 82 | #### 1.0.2 83 | * **Change**: Some translation fixes 84 | * **Change**: Better documentation and screenshot 85 | * **Added**: Italian translation. (Thanks to [cipo28](https://github.com/front/cloud-blocks/pull/1)) 86 | 87 | #### 1.0.1 88 | * **Fix**: is_plugin_active() undefined fix 89 | * **Fix**: Change strings functions to static 90 | 91 | #### 1.0.0 92 | * Initial plugin 93 | -------------------------------------------------------------------------------- /docs/create-block.md: -------------------------------------------------------------------------------- 1 | # How to create a custom block for Gutenberg Cloud 2 | 3 | Blocks for **Gutenberg Cloud** are just normal Gutenberg custom blocks with some meta. So here you go: The quick guide to making your first custom block! 4 | 5 | *Note: If you already know how to build a block, you can skip step 2.* 6 | 7 | ## Step 1 - Ask yourself: Do I need to make a new plugin? 8 | 9 | Mostly, no. If you are making a neatly designed layout, or providing Gutenberg with some handy settings in the sidebar, this is all JS/HTML/CSS. By sticking to front-end code, your block can be used not only in WP, but also in Drupal (and more)! 10 | 11 | 12 | If you are forced to use PHP for something on the server however, you can kickstart your plugin using [create-guten-block](https://github.com/ahmadawais/create-guten-block) (WP only). Even then, you might want to open source the front-end part, so other CMSs can use it. 13 | 14 | ## Step 2 - Build a block 15 | 16 | Let's build a “Hello World” block with some styling and sidebar settings. The easiest way to create a custom block is using the [Create Cloud Block](https://github.com/front/create-cloud-block) tool. 17 | 18 | The [Create Cloud Block](https://github.com/front/create-cloud-block) is a boilerplate generator for building custom blocks for Gutenberg Cloud and all we have to do is run `$ npx create-cloud-block hello-world` where ‘hello-world’ is the name of our custom block. This command will generate all the files we need to build our block. 19 | 20 | *Check generated files [here](https://github.com/SofiaSousa/hello-world/commit/5091f54683835b73813fb5d84c6a43e17cd32e93)* 21 | 22 | Once files are generated, we can compile and run our custom block in development mode. Let’s try by going to the block folder `$ cd hello-world` and running the follow command `$ npm start`. After the editor starts running in the browser, we can insert our custom block. By default, it should look like the following. 23 | 24 | ![Insert Custom Block](../assets/insert_custom_block.gif?sanitize=true "Insert Custom Block") 25 | 26 | Now, we can start by customizing our block! The files we should care about are in ‘src/hello-world’ folder (‘index.js’ and ‘style.css’). 27 | 28 | In 'src/hello-world/index.js', we can change the block name to 'Hello world', add 'My first custom block for Cloud blocks' to the description and use 'format-chat' icon. Our custom block sidebar should looks like this: 29 | 30 | ![Custom Block Sidebar](../assets/custom_block_sidebar.png?sanitize=true "Custom Block Sidebar") 31 | 32 | *Check files changes [here](https://github.com/SofiaSousa/hello-world/commit/247c1a05a32e8a9f2624ad01f9fd6efe60d5bc33)* 33 | 34 | For now, we can change block font size and text and background color in editor. Would be nice if we also could change the text align of the block. Let’s add the align attribute! 35 | 36 | First we have to add the new attribute to `BLOCK_ATTRIBUTES` object. Also we can set the default value. 37 | 38 | ```js 39 | // src/hello-world/index.js 40 | 41 | const BLOCK_ATTRIBUTES = { 42 | ... 43 | align: { 44 | type: 'string', 45 | default: 'center', 46 | }, 47 | }; 48 | 49 | ``` 50 | 51 | Then we can use **BlocksControls** and **AlignmentToolbar** components from editor Gutenberg module to add the align options to the block toolbar. 52 | 53 | ```js 54 | // src/hello-world/index.js 55 | 56 | const { 57 | AlignmentToolbar, 58 | BlocksControls, 59 | ... 60 | }; 61 | 62 | ``` 63 | 64 | ![Alignment Toolbar](../assets/alignment_toolbar.png?sanitize=true "Alignment Toolbar") 65 | 66 | Finally we only need to set the selected align value to the block content in `edit` and `save` methods and remove the css rule by default in 'src/hello-world/style.scss'. 67 | 68 | *Check all files changes [here](https://github.com/SofiaSousa/hello-world/commit/0b8d07d6d6f641f10eea714ce10803957a9020ae)* 69 | 70 | After the changes we can rebuild the block and run it in dev mode by running npm start command. 71 | 72 | ## Step 3 - Submit block to Gutenberg Cloud 73 | 74 | ### Add screenshot 75 | 76 | To improve the Gutenberg Cloud browsing experience, add a nice visual of your block in root, and list it in package.json files object (see below). 77 | 78 | - Screenshot name: screenshot.png 79 | - Image size: 1200px * 600px 80 | 81 | It’s a good idea to run your png through [TinyPNG](https://tinypng.com/) to make it light. 82 | 83 | ### Publish to NPM 84 | 85 | Make sure your README.md makes sense, and update the package.json values in gutenbergCloud object, and also `homepage`, `author` and `description`. Note that these will be visible in the UI when clicking to see More details. 86 | 87 | Note that you need the keywords, `gutenberg`and `gutenberg-cloud` for the block to work. Feel free to add some more, like: tags, social, map, etc. 88 | 89 | Custom blocks generated by create-cloud-block tool come with all configuration needed to be distributed by Cloud Blocks. Also they have a deploy script which complies the build files and publish the package to NPM, so all we have to do is run `$ npm run deploy`. 90 | 91 | After our review, your custom block is available to the world through [api.gutenbergcloud.org/blocks](https://api.gutenbergcloud.org/blocks). Congrats! 92 | 93 | ## Documentation 94 | 95 | That’s pretty much it! Before doing anything advanced: Read the official docs. Here are some good resources: 96 | 97 | - [Gutenberg handbook](https://wordpress.org/gutenberg/handbook/) (official docs) 98 | - [Example blocks on Github](https://github.com/WordPress/gutenberg-examples) 99 | - [New tutorials](http://gutenberg.news/category/tutorials/) (these get old fast) 100 | -------------------------------------------------------------------------------- /docs/hooks.md: -------------------------------------------------------------------------------- 1 | # Hooks 2 | 3 | ## How to disable CSS for a single block 4 | 5 | 6 | `gutenberg_cloud_disable_style` 7 | 8 | Disable blocks styling for single block: 9 | 10 | ```php 11 | add_filter( 'gutenberg_cloud_disable_style', 'disable_custom_blocks_styles', 10, 2); 12 | function disable_custom_blocks_styles( $exclude, $block ) { 13 | if ( $block->package_name == '@frontkom/g-content-in-columns') { 14 | return true; 15 | } 16 | return false; 17 | } 18 | ``` 19 | 20 | Or disable for all custom blocks: 21 | 22 | ```php 23 | add_filter( 'gutenberg_cloud_disable_style', 'disable_custom_blocks_styles', 10, 2); 24 | function disable_custom_blocks_styles( $exclude, $block ) { 25 | return true; 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/migrate-block.md: -------------------------------------------------------------------------------- 1 | # Migrating blocks from a plugin 2 | 3 | **If you already have a plugin with a collection of custom blocks and would like to add them to Gutenberg Cloud, follow these 10 steps.** 4 | 5 | ## 1. Initiate a new package for NPM 6 | 7 | First we should create our package structure, using [create-cloud-block](https://github.com/front/create-cloud-block). 8 | 9 | ```sh 10 | $ npx create-cloud-block name-of-block 11 | ``` 12 | 13 | This step takes time, as it will also download a standalone editor for testing. 14 | 15 | ## 2. Add two keywords to package.json 16 | 17 | Gutenberg Cloud looks for custom blocks in NPM repository, and it looks for the packages which have ‘gutenberg’ and ‘gutenberg-cloud’ keywords. So don’t forget to add these keywords in package.json. 18 | 19 | ```json 20 | { 21 | "keywords": [ 22 | "gutenberg", 23 | "gutenberg-cloud" 24 | ] 25 | } 26 | ``` 27 | 28 | Since you used create-cloud-block, these are already there. **Without these, Gutenberg Cloud will ignore your block.** 29 | 30 | Additionally, we recommend adding a couple of keywords describing what it does. Examples: social, map, hero, etc 31 | 32 | ## 3. Add gutenbergCloud object to package.json 33 | 34 | After fetching available blocks, Cloud Blocks plugin allows the user to install blocks and make them available in the editor. In order to help Cloud Blocks know the block index, style, screenshot and name, you must add the `gutenbergCloud` object to block package.json. 35 | 36 | ```json 37 | { 38 | "gutenbergCloud": { 39 | "js": "build/index.js", 40 | "css": "build/style.css", 41 | "screenshot": "screenshot.png", 42 | "name": "Hero section" 43 | } 44 | } 45 | ``` 46 | 47 | Needless to say, the name is pretty important. Stay descriptive, but some originality might be good to set your block apart. 48 | 49 | *Note: We are planning on adding more meta later, to allow for better filtering.* 50 | 51 | ## 4. Copy your plugin files into the new package 52 | 53 | Not all of them – you don’t need the PHP files. Here are some typical files/folders you will need to copy: 54 | 55 | - block index => /src/[block-name]/index.js 56 | - block style => /src/[block-name]/style.scss 57 | - block editor style => /src/[block-name]/editor.scss (only if necessary) 58 | 59 | Feel free to organize blocks files and dependencies as you prefer. This is only the suggestion the create-cloud-block tool gives us. 60 | 61 | The most important here is to make sure the block entry point is in src folder. Webpack will look for an index.js file at that folder before compiling and generating the build files. 62 | 63 | You are also free to change Webpack configuration if you feel comfortable with that, but at that point, we can’t ensure everything work as we planned and expected. If you will change Webpack configuration, make sure you also update file paths of `gutenbergCloud` object properties in package.json. 64 | 65 | *Note: If you find that you have to use PHP, Cloud Blocks is not the solution for this block.* 66 | 67 | ## 5. Check that paths to assets are ok 68 | 69 | This step is the most complex one. But if you are the plugin author, it should be quite easy! 70 | 71 | Let’s pretend we are moving a block from the excellent [Stackable block collection](https://wordpress.org/plugins/stackable-ultimate-gutenberg-blocks/). After we have initiated the project, we moved *Image Box* block files to our package src folder, as well as all the remaining dependency files (icons.js and wp-imports.js). 72 | 73 | ``` 74 | stackable-image-box 75 | ├── build 76 | ├── node_modules 77 | │ 78 | ├── src 79 | │ ├── stackable-image-box 80 | │ │ ├── deprecated.js 81 | │ │ ├── editor.scss 82 | │ │ ├── index.js 83 | │ │ └── style.scss 84 | │ ├── icons.js 85 | │ ├── index.js 86 | │ └── wp-imports.js 87 | │ 88 | ├── .babelrc 89 | ├── .eslintrc 90 | ├── .gitignore 91 | ├── package-lock.json 92 | ├── package.json 93 | ├── README.md 94 | ├── screenshoot.png 95 | └── webpack.config.js 96 | 97 | ``` 98 | 99 | According our folder structure, we have to update relative paths for imports in 'src/stackable-image-box/index.js', like: 100 | 101 | ```js 102 | import { PictureIcon } from '../icons'; 103 | import { ... } from '../wp-imports'; 104 | ``` 105 | 106 | In this case, we also removed some dependencies *Image Box* doesn’t use from wp-imports.js file and added box, baseBlock and blockContentReset mixins to style.css. 107 | 108 | ## 6. Make the block register itself 109 | 110 | Gutenberg provides several ways to register our custom blocks. Cloud Blocks expects custom blocks to be independent and autonomous: they must be able to register themself and for that they should use `registerBlockType` function. 111 | 112 | The create-cloud-blocks command generates the src/index.js file which takes care of the registration process (category registration and block registration). All you have to do is to import your block settings and pass them to `registerBlockType` function ([official docs here](https://wordpress.org/gutenberg/handbook/blocks/writing-your-first-block-type/#registering-the-block)). 113 | 114 | We recommend using the **Cloud Blocks** (`'cloudblocks'`) category instead of company name, so blocks and categories show up well organized in Insert Menu in the editor. The reason for this, is that people might install four cloud blocks – each from a different author. Then it makes sense to keep them all together. 115 | 116 | ## 7. Test your block outside of WordPress 117 | 118 | Before you publish your block, make sure it works and that it looks nice across all platforms. Since you used create-cloud-block, you just do the following: 119 | 120 | ```sh 121 | $ npm start 122 | ``` 123 | 124 | ## 8. Test your block inside WordPress 125 | 126 | 1. Install the **[Cloud Blocks plugin](https://wordpress.org/plugins/cloud-blocks/)** 127 | 2. Add your block folder into /wp-content/gutenberg-blocks/ (this is only for testing, you can remove when published on NPM) 128 | 3. Click the cloud icon in admin and browse to see if you block is there. Activate it. 129 | 4. Test it in Gutenberg editor 130 | 131 | ## 9. Add the screenshot 132 | 133 | Create a 1200*900 px png. Preferably, run it through [tinypng.com](https://tinypng.com/) before adding it to your package root. We recommend showing what the block actually looks like. But: Feel free to add your logo for shameless branding. 134 | 135 | ## 10. Publish to NPM 136 | 137 | Make sure your README.md makes sense, and update the package.json values for `homepage`, `author` and `description`. Note that these will be visible in the UI when clicking to see More details. 138 | 139 | Next step: 140 | 141 | 142 | ```sh 143 | $ npm run build 144 | $ npm publish 145 | ``` 146 | 147 | or just `$ npm run deploy` if you used create-cloud-block tool. 148 | 149 | That’s it! Your block will be available to Gutenberg Cloud after our review. Bravo! 150 | -------------------------------------------------------------------------------- /docs/private-blocks.md: -------------------------------------------------------------------------------- 1 | ### How can I add private custom blocks? 2 | 3 | Just add your custom blocks into **wp-content/uploads/gutenberg-blocks/** folder and install in Gutenberg Cloud. 4 | 5 | File structure must look like following: 6 | 7 | ``` 8 | wp-content/uploads/gutenberg-blocks 9 | │ 10 | ├── block-one 11 | │ ├─ package.json 12 | │ ├── build 13 | │ │ ├── screenshot.(png|jpg|gif) 14 | │ │ ├── style.css 15 | │ │ ├── editor.css (optional) 16 | │ │ └── index.js 17 | │ │ 18 | │ ├── your source files 19 | │ ... 20 | │ 21 | ├── block-two 22 | │ │ 23 | ... ... 24 | ``` 25 | 26 | **Note:** package.json file content must contain `gutenbergCloud` object like followig example: 27 | 28 | ```json 29 | { 30 | "gutenbergCloud": { 31 | "js": "build/index.js", 32 | "css": "build/style.css", 33 | "screenshot": "screenshot.png" 34 | } 35 | } 36 | ``` 37 | 38 | You can use any build tool you like, or simply write your blocks in plain css and vanilla javascript. But the block files must be under **/your-private-block/build/** folder and follow naming convention. 39 | 40 | #### Added in version 1.0.7 41 | 42 | You can now upload your block as a zip file within Cloud Blocks UI for local hosting. 43 | -------------------------------------------------------------------------------- /languages/cloud-blocks-it_IT.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/languages/cloud-blocks-it_IT.mo -------------------------------------------------------------------------------- /languages/cloud-blocks-it_IT.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Cloud Blocks\n" 4 | "POT-Creation-Date: 2019-01-02 10:06+0100\n" 5 | "PO-Revision-Date: 2019-01-02 10:08+0100\n" 6 | "Last-Translator: Gianluca Rosi \n" 7 | "Language-Team: \n" 8 | "Language: it_IT\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Generator: Poedit 2.2\n" 13 | "X-Poedit-Basepath: ..\n" 14 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 15 | "X-Poedit-Flags-xgettext: --add-comments=translators:\n" 16 | "X-Poedit-WPHeader: cloud-blocks.php\n" 17 | "X-Poedit-SourceCharset: UTF-8\n" 18 | "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" 19 | "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;" 20 | "_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 21 | "X-Poedit-SearchPath-0: .\n" 22 | "X-Poedit-SearchPathExcluded-0: *.js\n" 23 | 24 | #: core/Blocks/Explore.php:58 25 | msgid "" 26 | "The file you are trying to upload is not a supported file type. Please try " 27 | "again." 28 | msgstr "" 29 | "Il file che si sta tentando di caricare non è supportato tipo di file. Per " 30 | "favore riprova." 31 | 32 | #: core/Blocks/Explore.php:72 33 | #, php-format 34 | msgid "" 35 | "Your custom block %s installed successfully. You must activate it in " 36 | "local tab." 37 | msgstr "" 38 | "Blocco %s installato correttamente. Devi attivarlo nella scheda " 39 | "locale." 40 | 41 | #: core/Blocks/Explore.php:75 42 | msgid "There was a problem with the upload. Please try again." 43 | msgstr "Errore caricamento file. Riprovare." 44 | 45 | #: core/Blocks/Explore.php:112 46 | msgid "Upload block" 47 | msgstr "Carica blocco" 48 | 49 | #: core/Blocks/Explore.php:118 50 | msgid "If you have a custom Gutenberg block, you can upload it here." 51 | msgstr "" 52 | "Se si dispone di un blocco Gutenberg personalizzato, è possibile caricarlo " 53 | "qui." 54 | 55 | #: core/Blocks/Explore.php:120 56 | #, php-format 57 | msgid "" 58 | "If using Git, we recommend adjusting your .gitignore and commit your block " 59 | "in %s" 60 | msgstr "" 61 | "Se si utilizza Git, si consiglia di regolare il. gitignore e commit il " 62 | "blocco in %s " 63 | 64 | #: core/Blocks/Explore.php:122 65 | msgid "See documentation: Private blocks." 66 | msgstr "Vedere documentazione: blocchi privati." 67 | 68 | #: core/Blocks/Explore.php:127 69 | msgid "Zip file of block" 70 | msgstr "Carica blocco" 71 | 72 | #: core/Blocks/Explore.php:129 73 | msgid "Install now" 74 | msgstr "Installa ora" 75 | 76 | #: core/CloudBlocks.php:42 77 | msgid "Gutenberg is not enabled. Please try again after enabling." 78 | msgstr "Gutenberg non è abilitato. Riprovare dopo averlo attivato." 79 | 80 | #: core/Settings/Tools.php:72 81 | msgid "No file selected." 82 | msgstr "Nessun file selezionato." 83 | 84 | #: core/Settings/Tools.php:80 85 | msgid "Error uploading file. Please try again." 86 | msgstr "Errore caricamento file. Riprovare." 87 | 88 | #: core/Settings/Tools.php:86 core/Settings/Tools.php:112 89 | msgid "Incorrect file type" 90 | msgstr "Tipo di file sbagliato" 91 | 92 | #: core/Settings/Tools.php:98 93 | msgid "Empty file imported" 94 | msgstr "File importato vuoto" 95 | 96 | #: core/Settings/Tools.php:106 97 | #, php-format 98 | msgid "Block %s already installed." 99 | msgstr "Blocco %s già installato." 100 | 101 | #: core/Settings/Tools.php:109 102 | #, php-format 103 | msgid "Block %s installed successfully." 104 | msgstr "Blocco %s installato correttamente." 105 | 106 | #: core/Settings/Tools.php:194 107 | msgid "Tools" 108 | msgstr "Strumenti" 109 | 110 | #: core/Settings/Tools.php:208 111 | msgid "Gutenberg cloud configurations" 112 | msgstr "Configurazioni Gutenberg cloud" 113 | 114 | #: core/Settings/Tools.php:219 115 | msgid "Export installed blocks" 116 | msgstr "Esporta blocchi installati" 117 | 118 | #: core/Settings/Tools.php:222 119 | msgid "" 120 | "Export all your installed blocks from Gutenberg Cloud as JSON. Note: The " 121 | "content will not be exported." 122 | msgstr "" 123 | "Qui puoi esportare tutti i blocchi personalizzati installati da Gutenberg " 124 | "Cloud come file json, quindi importarli da qualsiasi altra parte." 125 | 126 | #: core/Settings/Tools.php:224 127 | msgid "Export file" 128 | msgstr "Esporta file" 129 | 130 | #: core/Settings/Tools.php:233 131 | msgid "Import custom blocks" 132 | msgstr "Importa blocchi personali" 133 | 134 | #: core/Settings/Tools.php:236 135 | msgid "Choose the JSON file you want to import." 136 | msgstr "Scegli il file JSON da importare." 137 | 138 | #: core/Settings/Tools.php:240 139 | msgid "Choose the file" 140 | msgstr "Scegli il file" 141 | 142 | #: core/Settings/Tools.php:251 143 | msgid "Import file" 144 | msgstr "Importa file" 145 | 146 | #: core/Settings/Translations.php:18 147 | msgid "Block" 148 | msgstr "Blocco" 149 | 150 | #: core/Settings/Translations.php:19 151 | msgid "The block" 152 | msgstr "Il blocco" 153 | 154 | #: core/Settings/Translations.php:20 155 | msgid "Delete" 156 | msgstr "Cancella" 157 | 158 | #: core/Settings/Translations.php:21 159 | msgid "Delete block" 160 | msgstr "Elimina blocco" 161 | 162 | #: core/Settings/Translations.php:22 163 | msgid "Install" 164 | msgstr "Installato" 165 | 166 | #: core/Settings/Translations.php:23 167 | msgid "Uninstall" 168 | msgstr "Disinstalla" 169 | 170 | #: core/Settings/Translations.php:24 171 | msgid "Local" 172 | msgstr "Locale" 173 | 174 | #: core/Settings/Translations.php:25 175 | msgid "Local block" 176 | msgstr "Blocco locale" 177 | 178 | #: core/Settings/Translations.php:26 179 | msgid "By" 180 | msgstr "Di" 181 | 182 | #: core/Settings/Translations.php:27 183 | msgid "Tags" 184 | msgstr "Tags" 185 | 186 | #: core/Settings/Translations.php:28 187 | msgid "Installed" 188 | msgstr "Installato" 189 | 190 | #: core/Settings/Translations.php:29 191 | msgid "Popular" 192 | msgstr "Popolare" 193 | 194 | #: core/Settings/Translations.php:30 195 | msgid "Latest" 196 | msgstr "Più recente" 197 | 198 | #: core/Settings/Translations.php:31 199 | msgid "Most used" 200 | msgstr "Più usato" 201 | 202 | #: core/Settings/Translations.php:32 203 | msgid "Search for blocks" 204 | msgstr "Cerca blocchi" 205 | 206 | #: core/Settings/Translations.php:33 207 | msgid "Search blocks..." 208 | msgstr "Cerca blocchi..." 209 | 210 | #: core/Settings/Translations.php:34 211 | msgid "Filter" 212 | msgstr "Filtra" 213 | 214 | #: core/Settings/Translations.php:35 215 | msgid "Update now" 216 | msgstr "Aggiorna ora" 217 | 218 | #: core/Settings/Translations.php:36 219 | msgid "Show more details" 220 | msgstr "Mostra più dettagli" 221 | 222 | #: core/Settings/Translations.php:37 223 | msgid "More details" 224 | msgstr "Più dettagli" 225 | 226 | #: core/Settings/Translations.php:38 227 | msgid "have been installed successfully." 228 | msgstr "è stato installato correttamente." 229 | 230 | #: core/Settings/Translations.php:39 231 | msgid "have been uninstalled successfully." 232 | msgstr "è stato disinstallato correttamente." 233 | 234 | #: core/Settings/Translations.php:40 235 | msgid "have been deleted successfully." 236 | msgstr "sono stati eliminati con successo." 237 | 238 | #: core/Settings/Translations.php:41 239 | msgid "have been updated successfully." 240 | msgstr "è stato aggiornato correttamente." 241 | 242 | #: core/Settings/Translations.php:42 243 | msgid "New version available." 244 | msgstr "Nuova versione disponibile." 245 | 246 | #: core/Settings/Translations.php:43 247 | msgid "Version" 248 | msgstr "Versione" 249 | 250 | #: core/Settings/Translations.php:44 251 | msgid "Visit homepage" 252 | msgstr "Visita la homepage" 253 | 254 | #: core/Settings/Translations.php:45 255 | msgid "Homepage" 256 | msgstr "Homepage" 257 | 258 | #: vendor/foadyousefi/seven-fields/src/Container/Container.php:196 259 | msgid "Actions" 260 | msgstr "Azioni" 261 | 262 | #. Plugin Name of the plugin/theme 263 | msgid "Cloud Blocks" 264 | msgstr "Cloud Blocks" 265 | 266 | #. Description of the plugin/theme 267 | msgid "Your library of Gutenberg blocks in the cloud" 268 | msgstr "La tua libreria di Gutenberg blocks nel cloud" 269 | 270 | #. Author of the plugin/theme 271 | msgid "Frontkom" 272 | msgstr "Frontkom" 273 | 274 | #. Author URI of the plugin/theme 275 | msgid "https://frontkom.no" 276 | msgstr "https://frontkom.no" 277 | 278 | #~ msgid "Blocks zip file" 279 | #~ msgstr "Blocca il file zip" 280 | -------------------------------------------------------------------------------- /languages/cloud-blocks-nb_NO.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/languages/cloud-blocks-nb_NO.mo -------------------------------------------------------------------------------- /languages/cloud-blocks-nb_NO.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Cloud Blocks\n" 4 | "POT-Creation-Date: 2019-01-02 10:03+0100\n" 5 | "PO-Revision-Date: 2019-01-24 10:15+0100\n" 6 | "Last-Translator: \n" 7 | "Language-Team: \n" 8 | "Language: nb_NO\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Generator: Poedit 2.2.1\n" 13 | "X-Poedit-Basepath: ..\n" 14 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 15 | "X-Poedit-Flags-xgettext: --add-comments=translators:\n" 16 | "X-Poedit-WPHeader: cloud-blocks.php\n" 17 | "X-Poedit-SourceCharset: UTF-8\n" 18 | "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" 19 | "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;" 20 | "_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 21 | "X-Poedit-SearchPath-0: .\n" 22 | "X-Poedit-SearchPathExcluded-0: *.js\n" 23 | 24 | #: core/Blocks/Explore.php:58 25 | msgid "" 26 | "The file you are trying to upload is not a supported file type. Please try " 27 | "again." 28 | msgstr "Filen du lastet har feil format. Vennligst prøv igjen." 29 | 30 | #: core/Blocks/Explore.php:72 31 | #, php-format 32 | msgid "" 33 | "Your custom block %s installed successfully. You must activate it in " 34 | "local tab." 35 | msgstr "" 36 | "Din custom blokk %s er nå installert. Du må aktivere den under fanen " 37 | "for lokale blokker." 38 | 39 | #: core/Blocks/Explore.php:75 40 | msgid "There was a problem with the upload. Please try again." 41 | msgstr "Noe gikk galt med opplastingen. Vennligst prøv igjen." 42 | 43 | #: core/Blocks/Explore.php:112 44 | msgid "Upload block" 45 | msgstr "Last opp blokk" 46 | 47 | #: core/Blocks/Explore.php:118 48 | msgid "If you have a custom Gutenberg block, you can upload it here." 49 | msgstr "" 50 | "Hvis du har en spesiallaget blokk for Gutenberg, kan den lastes opp her." 51 | 52 | #: core/Blocks/Explore.php:120 53 | #, php-format 54 | msgid "" 55 | "If using Git, we recommend adjusting your .gitignore and commit your block " 56 | "in %s" 57 | msgstr "" 58 | "Dersom du bruker Git, anbefaler vi å endre din .gitignore og plassere " 59 | "blokken i %s" 60 | 61 | #: core/Blocks/Explore.php:122 62 | msgid "See documentation: Private blocks." 63 | msgstr "Se dokumentasjon: Private blocks." 64 | 65 | #: core/Blocks/Explore.php:127 66 | msgid "Zip file of block" 67 | msgstr "Zip-fil av blokken" 68 | 69 | #: core/Blocks/Explore.php:129 70 | msgid "Install now" 71 | msgstr "Aktiver" 72 | 73 | #: core/CloudBlocks.php:42 74 | msgid "Gutenberg is not enabled. Please try again after enabling." 75 | msgstr "Gutenberg er ikke aktivert. Skru den på, og prøv igjen!" 76 | 77 | #: core/Settings/Tools.php:72 78 | msgid "No file selected." 79 | msgstr "Ingen fil er valgt." 80 | 81 | #: core/Settings/Tools.php:80 82 | msgid "Error uploading file. Please try again." 83 | msgstr "Feil med opplastingen av fil. Vennligst prøv igjen." 84 | 85 | #: core/Settings/Tools.php:86 core/Settings/Tools.php:112 86 | msgid "Incorrect file type" 87 | msgstr "Feil filtype" 88 | 89 | #: core/Settings/Tools.php:98 90 | msgid "Empty file imported" 91 | msgstr "Tom fil importert" 92 | 93 | #: core/Settings/Tools.php:106 94 | #, php-format 95 | msgid "Block %s already installed." 96 | msgstr "Pakken %s allerede installert." 97 | 98 | #: core/Settings/Tools.php:109 99 | #, php-format 100 | msgid "Block %s installed successfully." 101 | msgstr "Blokk %s ble installert." 102 | 103 | #: core/Settings/Tools.php:194 104 | msgid "Tools" 105 | msgstr "Verktøy" 106 | 107 | #: core/Settings/Tools.php:208 108 | msgid "Gutenberg cloud configurations" 109 | msgstr "Gutenberg cloud konfigurasjoner" 110 | 111 | #: core/Settings/Tools.php:219 112 | msgid "Export installed blocks" 113 | msgstr "Eksporter installerte blokker" 114 | 115 | #: core/Settings/Tools.php:222 116 | msgid "" 117 | "Export all your installed blocks from Gutenberg Cloud as JSON. Note: The " 118 | "content will not be exported." 119 | msgstr "" 120 | "Klikk for å eksportere aktive blokker fra Gutenberg Cloud som JSON. OBS: " 121 | "Innholdet blir ikke eksportert." 122 | 123 | #: core/Settings/Tools.php:224 124 | msgid "Export file" 125 | msgstr "Eksportfil" 126 | 127 | #: core/Settings/Tools.php:233 128 | msgid "Import custom blocks" 129 | msgstr "Importere egendefinerte blokker" 130 | 131 | #: core/Settings/Tools.php:236 132 | msgid "Choose the JSON file you want to import." 133 | msgstr "Velg JSON-filen du vil importere." 134 | 135 | #: core/Settings/Tools.php:240 136 | msgid "Choose the file" 137 | msgstr "Velg fil" 138 | 139 | #: core/Settings/Tools.php:251 140 | msgid "Import file" 141 | msgstr "Import fil" 142 | 143 | #: core/Settings/Translations.php:18 144 | msgid "Block" 145 | msgstr "Blokk" 146 | 147 | #: core/Settings/Translations.php:19 148 | msgid "The block" 149 | msgstr "Blokk" 150 | 151 | #: core/Settings/Translations.php:20 152 | msgid "Delete" 153 | msgstr "Slett" 154 | 155 | #: core/Settings/Translations.php:21 156 | msgid "Delete block" 157 | msgstr "Slett blokk" 158 | 159 | #: core/Settings/Translations.php:22 160 | msgid "Install" 161 | msgstr "Aktiver" 162 | 163 | #: core/Settings/Translations.php:23 164 | msgid "Uninstall" 165 | msgstr "Avinstaller" 166 | 167 | #: core/Settings/Translations.php:24 168 | msgid "Local" 169 | msgstr "Lokal" 170 | 171 | #: core/Settings/Translations.php:25 172 | msgid "Local block" 173 | msgstr "Local blokk" 174 | 175 | #: core/Settings/Translations.php:26 176 | msgid "By" 177 | msgstr "Av" 178 | 179 | #: core/Settings/Translations.php:27 180 | msgid "Tags" 181 | msgstr "Stikkord" 182 | 183 | #: core/Settings/Translations.php:28 184 | msgid "Installed" 185 | msgstr "Installert" 186 | 187 | #: core/Settings/Translations.php:29 188 | msgid "Popular" 189 | msgstr "Populær" 190 | 191 | #: core/Settings/Translations.php:30 192 | msgid "Latest" 193 | msgstr "Nyeste" 194 | 195 | #: core/Settings/Translations.php:31 196 | msgid "Most used" 197 | msgstr "Mest brukt" 198 | 199 | #: core/Settings/Translations.php:32 200 | msgid "Search for blocks" 201 | msgstr "Søk etter blokker" 202 | 203 | #: core/Settings/Translations.php:33 204 | msgid "Search blocks..." 205 | msgstr "Søk blokker..." 206 | 207 | #: core/Settings/Translations.php:34 208 | msgid "Filter" 209 | msgstr "Filter" 210 | 211 | #: core/Settings/Translations.php:35 212 | msgid "Update now" 213 | msgstr "Oppdater nå" 214 | 215 | #: core/Settings/Translations.php:36 216 | msgid "Show more details" 217 | msgstr "Vis flere detaljer" 218 | 219 | #: core/Settings/Translations.php:37 220 | msgid "More details" 221 | msgstr "Flere detaljer" 222 | 223 | #: core/Settings/Translations.php:38 224 | msgid "have been installed successfully." 225 | msgstr "er installert." 226 | 227 | #: core/Settings/Translations.php:39 228 | msgid "have been uninstalled successfully." 229 | msgstr "er avinstallert.." 230 | 231 | #: core/Settings/Translations.php:40 232 | msgid "have been deleted successfully." 233 | msgstr "er nå slettet." 234 | 235 | #: core/Settings/Translations.php:41 236 | msgid "have been updated successfully." 237 | msgstr "er oppdatert." 238 | 239 | #: core/Settings/Translations.php:42 240 | msgid "New version available." 241 | msgstr "Ny versjon tilgjengelig." 242 | 243 | #: core/Settings/Translations.php:43 244 | msgid "Version" 245 | msgstr "Versjon" 246 | 247 | #: core/Settings/Translations.php:44 248 | msgid "Visit homepage" 249 | msgstr "Besøk hjemmeside" 250 | 251 | #: core/Settings/Translations.php:45 252 | msgid "Homepage" 253 | msgstr "Hjemmeside" 254 | 255 | #: vendor/foadyousefi/seven-fields/src/Container/Container.php:196 256 | msgid "Actions" 257 | msgstr "Aksjoner" 258 | 259 | #. Plugin Name of the plugin/theme 260 | msgid "Cloud Blocks" 261 | msgstr "Cloud Blocks" 262 | 263 | #. Description of the plugin/theme 264 | msgid "Your library of Gutenberg blocks in the cloud" 265 | msgstr "Ditt bibliotek av Gutenberg blokker i skyen" 266 | 267 | #. Author of the plugin/theme 268 | msgid "Frontkom" 269 | msgstr "Frontkom" 270 | 271 | #. Author URI of the plugin/theme 272 | msgid "https://frontkom.no" 273 | msgstr "https://frontkom.no" 274 | 275 | #~ msgid "Frontkom - Fouad Yousefi" 276 | #~ msgstr "Frontkom - Foad Yousefi" 277 | 278 | #~ msgid "Gutenberg Cloud" 279 | #~ msgstr "Gutenberg Cloud" 280 | 281 | #~ msgid "Settings" 282 | #~ msgstr "Innstillinger" 283 | 284 | #~ msgid "Test" 285 | #~ msgstr "Test" 286 | 287 | #~ msgid "Test text field" 288 | #~ msgstr "Test tekstfelt" 289 | 290 | #~ msgid "Testing translations again" 291 | #~ msgstr "Tester oversettelse igjen" 292 | 293 | #~ msgid "pages" 294 | #~ msgstr "sider" 295 | -------------------------------------------------------------------------------- /languages/cloud-blocks-pl_PL.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/languages/cloud-blocks-pl_PL.mo -------------------------------------------------------------------------------- /languages/cloud-blocks-pl_PL.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Cloud Blocks\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2019-01-02 10:09+0100\n" 6 | "PO-Revision-Date: 2019-01-08 09:45+0000\n" 7 | "Last-Translator: \n" 8 | "Language-Team: Polish\n" 9 | "Language: pl\n" 10 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: 8bit\n" 14 | "X-Loco-Source-Locale: pl_PL\n" 15 | "X-Generator: Loco https://localise.biz/\n" 16 | "X-Poedit-Basepath: ..\n" 17 | "X-Poedit-Flags-xgettext: --add-comments=translators:\n" 18 | "X-Poedit-WPHeader: cloud-blocks.php\n" 19 | "X-Poedit-SourceCharset: UTF-8\n" 20 | "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" 21 | "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;" 22 | "_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 23 | "X-Poedit-SearchPath-0: .\n" 24 | "X-Poedit-SearchPathExcluded-0: *.js\n" 25 | "X-Loco-Parser: loco_parse_po" 26 | 27 | #: core/Blocks/Explore.php:58 28 | msgid "" 29 | "The file you are trying to upload is not a supported file type. Please try " 30 | "again." 31 | msgstr "" 32 | "Plik, który próbujesz załadować zawiera niepoprawne rozszerzenie. Spróbuj " 33 | "ponownie." 34 | 35 | #: core/Blocks/Explore.php:72 36 | #, php-format 37 | msgid "" 38 | "Your custom block %s installed successfully. You must activate it in " 39 | "local tab." 40 | msgstr "" 41 | "Twój blok %s został pomyślnie zainstalowany. Musisz go aktywować w " 42 | "zakładce \"Lokalne\"." 43 | 44 | #: core/Blocks/Explore.php:75 45 | msgid "There was a problem with the upload. Please try again." 46 | msgstr "Wystąpił problem z załadowaniem. Spróbuj ponownie." 47 | 48 | #: core/Blocks/Explore.php:112 49 | msgid "Upload block" 50 | msgstr "Załaduj blok" 51 | 52 | #: core/Blocks/Explore.php:118 53 | msgid "If you have a custom Gutenberg block, you can upload it here." 54 | msgstr "Jeśli posiadasz własny blok Gutenberga, możesz go załadować tutaj." 55 | 56 | #: core/Blocks/Explore.php:120 57 | #, php-format 58 | msgid "" 59 | "If using Git, we recommend adjusting your .gitignore and commit your block " 60 | "in %s" 61 | msgstr "" 62 | "Jeśli używasz repozytorium Git, sugerujemy dostosować plik .gitignore i " 63 | "dodać blok do %s" 64 | 65 | #: core/Blocks/Explore.php:122 66 | msgid "See documentation: Private blocks." 67 | msgstr "Zobacz dokumentację: Bloki prywatne." 68 | 69 | #: core/Blocks/Explore.php:127 70 | msgid "Zip file of block" 71 | msgstr "Zapakuj w .zip" 72 | 73 | #: core/Blocks/Explore.php:129 74 | msgid "Install now" 75 | msgstr "Instaluj teraz" 76 | 77 | #: core/CloudBlocks.php:42 78 | msgid "Gutenberg is not enabled. Please try again after enabling." 79 | msgstr "" 80 | "Wtyczka 'Gutenberg' nie jest aktywna. Prosimy spróbować ponownie po jej " 81 | "włączeniu." 82 | 83 | #: core/Settings/Tools.php:72 84 | msgid "No file selected." 85 | msgstr "Nie wybrano pliku." 86 | 87 | #: core/Settings/Tools.php:80 88 | msgid "Error uploading file. Please try again." 89 | msgstr "Wystąpił błąd podczas przesyłania. Prosimy spróbować ponownie." 90 | 91 | #: core/Settings/Tools.php:86 core/Settings/Tools.php:112 92 | msgid "Incorrect file type" 93 | msgstr "Niepoprawny typ pliku" 94 | 95 | #: core/Settings/Tools.php:98 96 | msgid "Empty file imported" 97 | msgstr "Załadowano pusty plik" 98 | 99 | #: core/Settings/Tools.php:106 100 | #, php-format 101 | msgid "Block %s already installed." 102 | msgstr "Blok %s jest już zainstalowany." 103 | 104 | #: core/Settings/Tools.php:109 105 | #, php-format 106 | msgid "Block %s installed successfully." 107 | msgstr "Blok %s został pomyślnie zainstalowany." 108 | 109 | #: core/Settings/Tools.php:194 110 | msgid "Tools" 111 | msgstr "Narzędzia" 112 | 113 | #: core/Settings/Tools.php:208 114 | msgid "Gutenberg cloud configurations" 115 | msgstr "Konfiguracja Chmury Gutenberga" 116 | 117 | #: core/Settings/Tools.php:219 118 | msgid "Export installed blocks" 119 | msgstr "Eksport zainstalowanych bloków" 120 | 121 | #: core/Settings/Tools.php:222 122 | msgid "" 123 | "Export all your installed blocks from Gutenberg Cloud as JSON. Note: The " 124 | "content will not be exported." 125 | msgstr "" 126 | "Eksport wszystkich zainstalowanych bloków z Chmury Gutenberga jako plik JSON." 127 | " Uwaga: Treść bloków nie będzie eksportowana." 128 | 129 | #: core/Settings/Tools.php:224 130 | msgid "Export file" 131 | msgstr "Eksport pliku" 132 | 133 | #: core/Settings/Tools.php:233 134 | msgid "Import custom blocks" 135 | msgstr "Import własnych bloków" 136 | 137 | #: core/Settings/Tools.php:236 138 | msgid "Choose the JSON file you want to import." 139 | msgstr "Wybierz plik JSON, który chcesz zaimportować." 140 | 141 | #: core/Settings/Tools.php:240 142 | msgid "Choose the file" 143 | msgstr "Wybierz plik" 144 | 145 | #: core/Settings/Tools.php:251 146 | msgid "Import file" 147 | msgstr "Import pliku" 148 | 149 | #: core/Settings/Translations.php:18 150 | msgid "Block" 151 | msgstr "Blok" 152 | 153 | #: core/Settings/Translations.php:19 154 | msgid "The block" 155 | msgstr "Blok" 156 | 157 | #: core/Settings/Translations.php:20 158 | msgid "Delete" 159 | msgstr "Usuń" 160 | 161 | #: core/Settings/Translations.php:21 162 | msgid "Delete block" 163 | msgstr "Usuń blok" 164 | 165 | #: core/Settings/Translations.php:22 166 | msgid "Install" 167 | msgstr "Instaluj" 168 | 169 | #: core/Settings/Translations.php:23 170 | msgid "Uninstall" 171 | msgstr "Odinstaluj" 172 | 173 | #: core/Settings/Translations.php:24 174 | msgid "Local" 175 | msgstr "Lokalne" 176 | 177 | #: core/Settings/Translations.php:25 178 | msgid "Local block" 179 | msgstr "Blok lokalny" 180 | 181 | #: core/Settings/Translations.php:26 182 | msgid "By" 183 | msgstr "Przez" 184 | 185 | #: core/Settings/Translations.php:27 186 | msgid "Tags" 187 | msgstr "Tagi" 188 | 189 | #: core/Settings/Translations.php:28 190 | msgid "Installed" 191 | msgstr "Zainstalowano" 192 | 193 | #: core/Settings/Translations.php:29 194 | msgid "Popular" 195 | msgstr "Popularne" 196 | 197 | #: core/Settings/Translations.php:30 198 | msgid "Latest" 199 | msgstr "Ostatnie" 200 | 201 | #: core/Settings/Translations.php:31 202 | msgid "Most used" 203 | msgstr "Najczęściej używane" 204 | 205 | #: core/Settings/Translations.php:32 206 | msgid "Search for blocks" 207 | msgstr "Wyszukiwanie bloków" 208 | 209 | #: core/Settings/Translations.php:33 210 | msgid "Search blocks..." 211 | msgstr "Szukaj bloku..." 212 | 213 | #: core/Settings/Translations.php:34 214 | msgid "Filter" 215 | msgstr "Filtr" 216 | 217 | #: core/Settings/Translations.php:35 218 | msgid "Update now" 219 | msgstr "Aktualizuj teraz" 220 | 221 | #: core/Settings/Translations.php:36 222 | msgid "Show more details" 223 | msgstr "Zobacz więcej szczegółów" 224 | 225 | #: core/Settings/Translations.php:37 226 | msgid "More details" 227 | msgstr "Więcej szczegółów" 228 | 229 | #: core/Settings/Translations.php:38 230 | msgid "have been installed successfully." 231 | msgstr "został pomyślnie zainstalowany." 232 | 233 | #: core/Settings/Translations.php:39 234 | msgid "have been uninstalled successfully." 235 | msgstr "został pomyślnie odinstalowany." 236 | 237 | #: core/Settings/Translations.php:40 238 | msgid "have been deleted successfully." 239 | msgstr "został pomyślnie usunięty." 240 | 241 | #: core/Settings/Translations.php:41 242 | msgid "have been updated successfully." 243 | msgstr "został pomyślnie zaktualizowany." 244 | 245 | #: core/Settings/Translations.php:42 246 | msgid "New version available." 247 | msgstr "Dostępna jest nowa wersja." 248 | 249 | #: core/Settings/Translations.php:43 250 | msgid "Version" 251 | msgstr "Wersja" 252 | 253 | #: core/Settings/Translations.php:44 254 | msgid "Visit homepage" 255 | msgstr "Odwiedź stronę bloku" 256 | 257 | #: core/Settings/Translations.php:45 258 | msgid "Homepage" 259 | msgstr "Strona Bloku" 260 | 261 | #: vendor/foadyousefi/seven-fields/src/Container/Container.php:196 262 | msgid "Actions" 263 | msgstr "Akcje" 264 | 265 | #. Plugin Name of the plugin/theme 266 | msgid "Cloud Blocks" 267 | msgstr "Cloud Blocks" 268 | 269 | #. Description of the plugin/theme 270 | msgid "Your library of Gutenberg blocks in the cloud" 271 | msgstr "Twoja biblioteka Bloków Gutenberga w chmurze" 272 | 273 | #. Author of the plugin/theme 274 | msgid "Frontkom" 275 | msgstr "Frontkom" 276 | 277 | #. Author URI of the plugin/theme 278 | msgid "https://frontkom.no" 279 | msgstr "https://frontkom.no" 280 | -------------------------------------------------------------------------------- /languages/cloud-blocks-pt.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/languages/cloud-blocks-pt.mo -------------------------------------------------------------------------------- /languages/cloud-blocks-pt.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Cloud Blocks\n" 4 | "POT-Creation-Date: 2019-01-02 10:09+0100\n" 5 | "PO-Revision-Date: 2019-01-02 10:09+0100\n" 6 | "Last-Translator: \n" 7 | "Language-Team: \n" 8 | "Language: pt\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Generator: Poedit 2.2\n" 13 | "X-Poedit-Basepath: ..\n" 14 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 15 | "X-Poedit-Flags-xgettext: --add-comments=translators:\n" 16 | "X-Poedit-WPHeader: cloud-blocks.php\n" 17 | "X-Poedit-SourceCharset: UTF-8\n" 18 | "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" 19 | "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;" 20 | "_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 21 | "X-Poedit-SearchPath-0: .\n" 22 | "X-Poedit-SearchPathExcluded-0: *.js\n" 23 | 24 | #: core/Blocks/Explore.php:58 25 | msgid "" 26 | "The file you are trying to upload is not a supported file type. Please try " 27 | "again." 28 | msgstr "Erro ao carregar o ficheiro. Por favor, tente novamente." 29 | 30 | #: core/Blocks/Explore.php:72 31 | #, php-format 32 | msgid "" 33 | "Your custom block %s installed successfully. You must activate it in " 34 | "local tab." 35 | msgstr "" 36 | "Bloco %s instalado com êxito. Você deve ativá-lo na guia local." 37 | 38 | #: core/Blocks/Explore.php:75 39 | msgid "There was a problem with the upload. Please try again." 40 | msgstr "Erro ao carregar o ficheiro. Por favor, tente novamente." 41 | 42 | #: core/Blocks/Explore.php:112 43 | msgid "Upload block" 44 | msgstr "Blocos da nuvem" 45 | 46 | #: core/Blocks/Explore.php:118 47 | msgid "If you have a custom Gutenberg block, you can upload it here." 48 | msgstr "" 49 | "Se você tem um bloco personalizado de Gutenberg, você pode carregá-lo aqui." 50 | 51 | #: core/Blocks/Explore.php:120 52 | #, php-format 53 | msgid "" 54 | "If using Git, we recommend adjusting your .gitignore and commit your block " 55 | "in %s" 56 | msgstr "" 57 | "Se estiver usando o Git, recomendamos ajustar o seu. gitignore e confirmar " 58 | "seu bloco em %s " 59 | 60 | #: core/Blocks/Explore.php:122 61 | msgid "See documentation: Private blocks." 62 | msgstr "Consulte a documentação: blocos privados." 63 | 64 | #: core/Blocks/Explore.php:127 65 | msgid "Zip file of block" 66 | msgstr "Blocos da nuvem" 67 | 68 | #: core/Blocks/Explore.php:129 69 | msgid "Install now" 70 | msgstr "Instalado" 71 | 72 | #: core/CloudBlocks.php:42 73 | msgid "Gutenberg is not enabled. Please try again after enabling." 74 | msgstr "" 75 | "O Gutenberg não está activado. Por favor, tente novamente após activá-lo." 76 | 77 | #: core/Settings/Tools.php:72 78 | msgid "No file selected." 79 | msgstr "Nenhum ficheiro selecionado." 80 | 81 | #: core/Settings/Tools.php:80 82 | msgid "Error uploading file. Please try again." 83 | msgstr "Erro ao carregar o ficheiro. Por favor, tente novamente." 84 | 85 | #: core/Settings/Tools.php:86 core/Settings/Tools.php:112 86 | msgid "Incorrect file type" 87 | msgstr "Tipo de ficheiro incorreto" 88 | 89 | #: core/Settings/Tools.php:98 90 | msgid "Empty file imported" 91 | msgstr "Arquivo vazio importado" 92 | 93 | #: core/Settings/Tools.php:106 94 | #, php-format 95 | msgid "Block %s already installed." 96 | msgstr "Bloco %s já está instalado." 97 | 98 | #: core/Settings/Tools.php:109 99 | #, php-format 100 | msgid "Block %s installed successfully." 101 | msgstr "Bloco %s instalado com êxito." 102 | 103 | #: core/Settings/Tools.php:194 104 | msgid "Tools" 105 | msgstr "Ferramentas" 106 | 107 | #: core/Settings/Tools.php:208 108 | msgid "Gutenberg cloud configurations" 109 | msgstr "Configurações da nuvem de Gutenberg" 110 | 111 | #: core/Settings/Tools.php:219 112 | msgid "Export installed blocks" 113 | msgstr "Exportar blocos instalados" 114 | 115 | #: core/Settings/Tools.php:222 116 | msgid "" 117 | "Export all your installed blocks from Gutenberg Cloud as JSON. Note: The " 118 | "content will not be exported." 119 | msgstr "" 120 | "Aqui você pode exportar todos os blocos personalizados Gutenberg instalados " 121 | "da nuvem de Gutenberg como um ficheiro JSON e importá-lo em outro lugar." 122 | 123 | #: core/Settings/Tools.php:224 124 | msgid "Export file" 125 | msgstr "Exportar Arquivo" 126 | 127 | #: core/Settings/Tools.php:233 128 | msgid "Import custom blocks" 129 | msgstr "Importar blocos personalizados" 130 | 131 | #: core/Settings/Tools.php:236 132 | msgid "Choose the JSON file you want to import." 133 | msgstr "Escolha o ficheiro JSON que você deseja importar." 134 | 135 | #: core/Settings/Tools.php:240 136 | msgid "Choose the file" 137 | msgstr "Escolha o ficheiro" 138 | 139 | #: core/Settings/Tools.php:251 140 | msgid "Import file" 141 | msgstr "Importar ficheiro" 142 | 143 | #: core/Settings/Translations.php:18 144 | msgid "Block" 145 | msgstr "Bloco" 146 | 147 | #: core/Settings/Translations.php:19 148 | msgid "The block" 149 | msgstr "O bloco" 150 | 151 | #: core/Settings/Translations.php:20 152 | msgid "Delete" 153 | msgstr "Excluir" 154 | 155 | #: core/Settings/Translations.php:21 156 | msgid "Delete block" 157 | msgstr "Excluir bloco" 158 | 159 | #: core/Settings/Translations.php:22 160 | msgid "Install" 161 | msgstr "Instalado" 162 | 163 | #: core/Settings/Translations.php:23 164 | msgid "Uninstall" 165 | msgstr "Desinstalar" 166 | 167 | #: core/Settings/Translations.php:24 168 | msgid "Local" 169 | msgstr "Local" 170 | 171 | #: core/Settings/Translations.php:25 172 | msgid "Local block" 173 | msgstr "Bloco local" 174 | 175 | #: core/Settings/Translations.php:26 176 | msgid "By" 177 | msgstr "Por" 178 | 179 | #: core/Settings/Translations.php:27 180 | msgid "Tags" 181 | msgstr "Etiquetas" 182 | 183 | #: core/Settings/Translations.php:28 184 | msgid "Installed" 185 | msgstr "Instalado" 186 | 187 | #: core/Settings/Translations.php:29 188 | msgid "Popular" 189 | msgstr "Popular" 190 | 191 | #: core/Settings/Translations.php:30 192 | msgid "Latest" 193 | msgstr "Mais recentes" 194 | 195 | #: core/Settings/Translations.php:31 196 | msgid "Most used" 197 | msgstr "Mais utilizados" 198 | 199 | #: core/Settings/Translations.php:32 200 | msgid "Search for blocks" 201 | msgstr "Procurar blocos" 202 | 203 | #: core/Settings/Translations.php:33 204 | msgid "Search blocks..." 205 | msgstr "Blocos de busca..." 206 | 207 | #: core/Settings/Translations.php:34 208 | msgid "Filter" 209 | msgstr "Filtro" 210 | 211 | #: core/Settings/Translations.php:35 212 | msgid "Update now" 213 | msgstr "Atualizar agora" 214 | 215 | #: core/Settings/Translations.php:36 216 | msgid "Show more details" 217 | msgstr "Mostrar mais detalhes" 218 | 219 | #: core/Settings/Translations.php:37 220 | msgid "More details" 221 | msgstr "Mais detalhes" 222 | 223 | #: core/Settings/Translations.php:38 224 | msgid "have been installed successfully." 225 | msgstr "foram instalados com êxito." 226 | 227 | #: core/Settings/Translations.php:39 228 | msgid "have been uninstalled successfully." 229 | msgstr "foram desinstaladas com êxito." 230 | 231 | #: core/Settings/Translations.php:40 232 | msgid "have been deleted successfully." 233 | msgstr "foram eliminados com êxito." 234 | 235 | #: core/Settings/Translations.php:41 236 | msgid "have been updated successfully." 237 | msgstr "foram atualizados com sucesso." 238 | 239 | #: core/Settings/Translations.php:42 240 | msgid "New version available." 241 | msgstr "Nova versão disponível." 242 | 243 | #: core/Settings/Translations.php:43 244 | msgid "Version" 245 | msgstr "Versão" 246 | 247 | #: core/Settings/Translations.php:44 248 | msgid "Visit homepage" 249 | msgstr "Visite a homepage" 250 | 251 | #: core/Settings/Translations.php:45 252 | msgid "Homepage" 253 | msgstr "Homepage" 254 | 255 | #: vendor/foadyousefi/seven-fields/src/Container/Container.php:196 256 | msgid "Actions" 257 | msgstr "Ações" 258 | 259 | #. Plugin Name of the plugin/theme 260 | msgid "Cloud Blocks" 261 | msgstr "Blocos da nuvem" 262 | 263 | #. Description of the plugin/theme 264 | msgid "Your library of Gutenberg blocks in the cloud" 265 | msgstr "Sua biblioteca de Gutenberg bloqueia na nuvem" 266 | 267 | #. Author of the plugin/theme 268 | msgid "Frontkom" 269 | msgstr "Frontkom" 270 | 271 | #. Author URI of the plugin/theme 272 | msgid "https://frontkom.no" 273 | msgstr "https://frontkom.no" 274 | 275 | #~ msgid "Blocks zip file" 276 | #~ msgstr "Bloqueia o arquivo zip" 277 | 278 | #~ msgid "Frontkom - Fouad Yousefi" 279 | #~ msgstr "Frontkom-Fuad Yousefi" 280 | -------------------------------------------------------------------------------- /languages/cloud-blocks-pt_PT.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/front/cloud-blocks/ded5141a8b460c69292040d3badcf243ce021fc3/languages/cloud-blocks-pt_PT.mo -------------------------------------------------------------------------------- /languages/cloud-blocks-pt_PT.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Cloud Blocks\n" 4 | "POT-Creation-Date: 2019-01-02 10:10+0100\n" 5 | "PO-Revision-Date: 2019-01-02 10:33+0100\n" 6 | "Last-Translator: \n" 7 | "Language-Team: \n" 8 | "Language: pt_PT\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Generator: Poedit 2.2\n" 13 | "X-Poedit-Basepath: ..\n" 14 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 15 | "X-Poedit-Flags-xgettext: --add-comments=translators:\n" 16 | "X-Poedit-WPHeader: cloud-blocks.php\n" 17 | "X-Poedit-SourceCharset: UTF-8\n" 18 | "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" 19 | "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;" 20 | "_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 21 | "X-Poedit-SearchPath-0: .\n" 22 | "X-Poedit-SearchPathExcluded-0: *.js\n" 23 | 24 | #: core/Blocks/Explore.php:58 25 | msgid "" 26 | "The file you are trying to upload is not a supported file type. Please try " 27 | "again." 28 | msgstr "Tipo de ficheiro não suportado. Por favor, tente novamente." 29 | 30 | #: core/Blocks/Explore.php:72 31 | #, php-format 32 | msgid "" 33 | "Your custom block %s installed successfully. You must activate it in " 34 | "local tab." 35 | msgstr "" 36 | "O seu bloco personalizado %s foi instalado com sucesso. Terá de " 37 | "activá-lo na tab Local." 38 | 39 | #: core/Blocks/Explore.php:75 40 | msgid "There was a problem with the upload. Please try again." 41 | msgstr "" 42 | "Ocorreu um problema durante o carregamento. Por favor, tente novamente." 43 | 44 | #: core/Blocks/Explore.php:112 45 | msgid "Upload block" 46 | msgstr "Carregar bloco" 47 | 48 | #: core/Blocks/Explore.php:118 49 | msgid "If you have a custom Gutenberg block, you can upload it here." 50 | msgstr "" 51 | "Se tem um bloco Gutenberg personalizado no formato .zip pode instalá-lo " 52 | "carregando-o aqui." 53 | 54 | #: core/Blocks/Explore.php:120 55 | #, php-format 56 | msgid "" 57 | "If using Git, we recommend adjusting your .gitignore and commit your block " 58 | "in %s" 59 | msgstr "" 60 | "Se usa o Git, recomendamos que altere o seu .gitignore e coloque o seu bloco " 61 | "na diretoria %s" 62 | 63 | #: core/Blocks/Explore.php:122 64 | msgid "See documentation: Private blocks." 65 | msgstr "Ver documentação: blocos privados" 66 | 67 | #: core/Blocks/Explore.php:127 68 | msgid "Zip file of block" 69 | msgstr "Ficheiro zip do bloco" 70 | 71 | #: core/Blocks/Explore.php:129 72 | msgid "Install now" 73 | msgstr "Instalar agora" 74 | 75 | #: core/CloudBlocks.php:42 76 | msgid "Gutenberg is not enabled. Please try again after enabling." 77 | msgstr "" 78 | "O Gutenberg não está activado. Por favor, tente novamente após activá-lo." 79 | 80 | #: core/Settings/Tools.php:72 81 | msgid "No file selected." 82 | msgstr "Nenhum ficheiro selecionado." 83 | 84 | #: core/Settings/Tools.php:80 85 | msgid "Error uploading file. Please try again." 86 | msgstr "Erro ao carregar o ficheiro. Por favor, tente novamente." 87 | 88 | #: core/Settings/Tools.php:86 core/Settings/Tools.php:112 89 | msgid "Incorrect file type" 90 | msgstr "Tipo de ficheiro incorreto" 91 | 92 | #: core/Settings/Tools.php:98 93 | msgid "Empty file imported" 94 | msgstr "O ficheiro importado está vazio" 95 | 96 | #: core/Settings/Tools.php:106 97 | #, php-format 98 | msgid "Block %s already installed." 99 | msgstr "O bloco %s já foi instalado." 100 | 101 | #: core/Settings/Tools.php:109 102 | #, php-format 103 | msgid "Block %s installed successfully." 104 | msgstr "O bloco %s foi instalado com sucesso." 105 | 106 | #: core/Settings/Tools.php:194 107 | msgid "Tools" 108 | msgstr "Ferramentas" 109 | 110 | #: core/Settings/Tools.php:208 111 | msgid "Gutenberg cloud configurations" 112 | msgstr "Configurações da Gutenberg cloud" 113 | 114 | #: core/Settings/Tools.php:219 115 | msgid "Export installed blocks" 116 | msgstr "Exportar blocos instalados" 117 | 118 | #: core/Settings/Tools.php:222 119 | msgid "" 120 | "Export all your installed blocks from Gutenberg Cloud as JSON. Note: The " 121 | "content will not be exported." 122 | msgstr "" 123 | "Exportar da Gutenberg Could todos os blocos instalados para um ficheiro " 124 | "JSON. Nota: o conteúdo não será exportado." 125 | 126 | #: core/Settings/Tools.php:224 127 | msgid "Export file" 128 | msgstr "Exportar Ficheiro" 129 | 130 | #: core/Settings/Tools.php:233 131 | msgid "Import custom blocks" 132 | msgstr "Importar blocos personalizados" 133 | 134 | #: core/Settings/Tools.php:236 135 | msgid "Choose the JSON file you want to import." 136 | msgstr "Escolha o ficheiro JSON que deseja importar." 137 | 138 | #: core/Settings/Tools.php:240 139 | msgid "Choose the file" 140 | msgstr "Escolha o ficheiro" 141 | 142 | #: core/Settings/Tools.php:251 143 | msgid "Import file" 144 | msgstr "Importar ficheiro" 145 | 146 | #: core/Settings/Translations.php:18 147 | msgid "Block" 148 | msgstr "Bloco" 149 | 150 | #: core/Settings/Translations.php:19 151 | msgid "The block" 152 | msgstr "O bloco" 153 | 154 | #: core/Settings/Translations.php:20 155 | msgid "Delete" 156 | msgstr "Excluir" 157 | 158 | #: core/Settings/Translations.php:21 159 | msgid "Delete block" 160 | msgstr "Apagar o bloco" 161 | 162 | #: core/Settings/Translations.php:22 163 | msgid "Install" 164 | msgstr "Instalar" 165 | 166 | #: core/Settings/Translations.php:23 167 | msgid "Uninstall" 168 | msgstr "Desinstalar" 169 | 170 | #: core/Settings/Translations.php:24 171 | msgid "Local" 172 | msgstr "Local" 173 | 174 | #: core/Settings/Translations.php:25 175 | msgid "Local block" 176 | msgstr "Bloco local" 177 | 178 | #: core/Settings/Translations.php:26 179 | msgid "By" 180 | msgstr "Por" 181 | 182 | #: core/Settings/Translations.php:27 183 | msgid "Tags" 184 | msgstr "Etiquetas" 185 | 186 | #: core/Settings/Translations.php:28 187 | msgid "Installed" 188 | msgstr "Instalado" 189 | 190 | #: core/Settings/Translations.php:29 191 | msgid "Popular" 192 | msgstr "Popular" 193 | 194 | #: core/Settings/Translations.php:30 195 | msgid "Latest" 196 | msgstr "Mais recentes" 197 | 198 | #: core/Settings/Translations.php:31 199 | msgid "Most used" 200 | msgstr "Mais utilizados" 201 | 202 | #: core/Settings/Translations.php:32 203 | msgid "Search for blocks" 204 | msgstr "Procurar blocos" 205 | 206 | #: core/Settings/Translations.php:33 207 | msgid "Search blocks..." 208 | msgstr "Pesquisar blocos…" 209 | 210 | #: core/Settings/Translations.php:34 211 | msgid "Filter" 212 | msgstr "Filtro" 213 | 214 | #: core/Settings/Translations.php:35 215 | msgid "Update now" 216 | msgstr "Atualizar agora" 217 | 218 | #: core/Settings/Translations.php:36 219 | msgid "Show more details" 220 | msgstr "Mostrar mais detalhes" 221 | 222 | #: core/Settings/Translations.php:37 223 | msgid "More details" 224 | msgstr "Mais detalhes" 225 | 226 | #: core/Settings/Translations.php:38 227 | msgid "have been installed successfully." 228 | msgstr "foi instalado com sucesso." 229 | 230 | #: core/Settings/Translations.php:39 231 | msgid "have been uninstalled successfully." 232 | msgstr "foi desinstalado com sucesso." 233 | 234 | #: core/Settings/Translations.php:40 235 | msgid "have been deleted successfully." 236 | msgstr "foi apagado com sucesso." 237 | 238 | #: core/Settings/Translations.php:41 239 | msgid "have been updated successfully." 240 | msgstr "foi atualizado com sucesso." 241 | 242 | #: core/Settings/Translations.php:42 243 | msgid "New version available." 244 | msgstr "Nova versão disponível." 245 | 246 | #: core/Settings/Translations.php:43 247 | msgid "Version" 248 | msgstr "Versão" 249 | 250 | #: core/Settings/Translations.php:44 251 | msgid "Visit homepage" 252 | msgstr "Visite a homepage" 253 | 254 | #: core/Settings/Translations.php:45 255 | msgid "Homepage" 256 | msgstr "Homepage" 257 | 258 | #: vendor/foadyousefi/seven-fields/src/Container/Container.php:196 259 | msgid "Actions" 260 | msgstr "Ações" 261 | 262 | #. Plugin Name of the plugin/theme 263 | msgid "Cloud Blocks" 264 | msgstr "Cloud Blocks" 265 | 266 | #. Description of the plugin/theme 267 | msgid "Your library of Gutenberg blocks in the cloud" 268 | msgstr "A sua biblioteca de blocos do Gutenberg na cloud" 269 | 270 | #. Author of the plugin/theme 271 | msgid "Frontkom" 272 | msgstr "Frontkom" 273 | 274 | #. Author URI of the plugin/theme 275 | msgid "https://frontkom.no" 276 | msgstr "https://frontkom.no" 277 | 278 | #~ msgid "Frontkom - Fouad Yousefi" 279 | #~ msgstr "Frontkom-Foad Yousefi" 280 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloud-blocks", 3 | "version": "1.0.0", 4 | "description": "Your library of Gutenberg blocks in the cloud", 5 | "scripts": { 6 | "styles:compile": "node-sass -w assets/source/scss/style.scss -o assets/source/scss/", 7 | "styles:prefix": "postcss assets/source/scss/style.css -u autoprefixer -b \"last 2 versions\" --no-map -o assets/css/style.css -w", 8 | "styles": "concurrently \"npm run styles:compile\" \"npm run styles:prefix\"", 9 | "babel": "babel --presets minify assets/js/script.js -o assets/js/script.min.js", 10 | "combine": "concat -o assets/js/script.js assets/source/js/*", 11 | "scripts": "concurrently \"npm run combine\" \"npm run babel\" " 12 | }, 13 | "babel": { 14 | "presets": [ 15 | [ 16 | "@babel/env", 17 | { 18 | "targets": { 19 | "browsers": [ 20 | "last 2 versions", 21 | "safari >= 7" 22 | ] 23 | } 24 | } 25 | ] 26 | ] 27 | }, 28 | "author": "Foad Yousefi", 29 | "license": "GPL2", 30 | "devDependencies": { 31 | "@babel/cli": "^7.2.3", 32 | "@babel/core": "^7.2.2", 33 | "@babel/preset-env": "^7.3.1", 34 | "autoprefixer": "^8.4.1", 35 | "babel-preset-minify": "^0.4.3", 36 | "babel-watch": "^2.0.8", 37 | "concat": "^1.0.3", 38 | "concurrently": "^3.5.1", 39 | "node-sass": "^4.11.0", 40 | "postcss-cli": "^5.0.0" 41 | }, 42 | "dependencies": {} 43 | } 44 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === Cloud Blocks === 2 | Contributors: frontkom, foadyousefi, ajotka, ssousa 3 | Author URI: https://frontkom.no 4 | Tags: gutenberg, pagebuilder, blocks, gutenberg blocks, page builder 5 | Requires at least: 4.9.8 6 | Tested up to: 5.2 7 | Requires PHP: 5.4 8 | Stable tag: 1.1.7 9 | License: GPLv3 10 | License URI: https://www.gnu.org/licenses/gpl-3.0.html 11 | 12 | Your online library of Gutenberg blocks! Browse and discover new blocks, and install with a click. 13 | 14 | == Description == 15 | 16 | **Gutenberg Cloud: Your online library of blocks!** Cloud Blocks is the only plugin you need to browse and install new blocks: 17 | 18 | - Discover and install custom blocks with a click 19 | - Install only the blocks you need – no huge plugin collections needed 20 | - Reuse blocks between WordPress and Drupal 21 | - Serve the blocks from a CDN 22 | 23 | ## Why use Gutenberg Cloud? 24 | Installing an actual plugin for each block or block collection easily leads to managing lots of code that you don’t really need. It’s like having one app for each website you visit, instead of just installing a web browser. With the block manager, you have a growing library at your fingertips, without the bloat. 25 | 26 | ## Getting started 27 | 1. Install the plugin 28 | 2. Click the new cloud icon in the main menu 29 | 3. Browse around and click a block to see description, version and bigger screenshot 30 | 4. Activate a few blocks. Voila – these are now available to you in the Gutenberg editor! 31 | 32 | ## How it works under the hood 33 | Gutenberg Cloud is a service that fetches Open Source Gutenberg blocks hosted on NPM. The assets from these are served from CloudFlare using jsdelivr.com. The Cloud Blocks plugin provides an interface in WordPress for Gutenberg Cloud. 34 | 35 | Code once, use everywhere: Since the blocks are JS/CSS only, they are CMS agnostic. This means you can develop a block for a Drupal site, and reuse it later on a WordPress blog. 36 | 37 | 38 | == Installation == 39 | Install it just like any other plugin. It just works! 40 | 41 | == Screenshots == 42 | 43 | 1. Discover and install blocks 44 | 45 | == Frequently Asked Questions == 46 | 47 | **Is it secure to run blocks from other people?** 48 | 49 | All blocks go through a manual code review before they are published. Waiting for a code review? Email perandre@front.no. 50 | 51 | **How do I migrate a block collection plugin to Gutenberg Cloud?** 52 | 53 | This simply means removing some PHP, adding some meta data and publishing on NPM. [Follow these simple steps](https://github.com/front/cloud-blocks/blob/master/docs/migrate-block.md). 54 | 55 | **How do I create a custom block for Gutenberg Cloud?** 56 | 57 | Gutenberg Cloud blocks are really just normal Gutenberg blocks, without the PHP. [Follow these steps to do it](https://github.com/front/cloud-blocks/blob/master/docs/create-block.md)! 58 | 59 | **How do I disable CSS for a single block?** 60 | 61 | This is useful for letting your theme control your block styles. There’s a hook for this, [documented here](https://github.com/front/cloud-blocks/blob/master/docs/hooks.md). 62 | 63 | **Why is the plugin called Cloud Blocks?** 64 | 65 | We wanted to name it Gutenberg Cloud, but since it’s not possible to name a plugin starting with the name of another plugin (i.e. Gutenberg), we ended up calling it Cloud Blocks. Makes sense though, doesn’t it? 66 | 67 | **Are the blocks really served from "the cloud"?** 68 | 69 | Indeed, they are! The source code for each block is on NPM, but the JS/CSS is served by a CDN. No local downloads! 70 | 71 | **Can I add private custom blocks?** 72 | 73 | Sure! Just add your custom blocks into **wp-content/uploads/gutenberg-blocks/** folder. [This is what the folder structure should look like](https://github.com/front/cloud-blocks/blob/master/docs/private-blocks.md)! 74 | 75 | 76 | == Changelog == 77 | 78 | = 1.1.8 = 79 | *Fix: Fix an issue with local blocks directory which was losting every files as block 80 | 81 | = 1.1.7 = 82 | * Fix: Fix db error in activator hook 83 | * Change: Dlete db table on plugin uninstallation 84 | 85 | = 1.1.6 = 86 | * Fix: Fix missing slash in local blocks 87 | 88 | = 1.1.5 = 89 | * Change: Replace unpkg.com CDN in favor of jsdelivr.com 90 | 91 | = 1.1.4 = 92 | * Change: Update counter as a WP CRON (Thanks to [ajotka](https://github.com/front/cloud-blocks/pull/14)) 93 | * Change: Update some docs 94 | * Fix: Fix polish translations 95 | 96 | = 1.1.3 = 97 | * Fix: Fix some translations 98 | * Fix: Fix database table issue if plugin network activated [issue #13](https://github.com/front/cloud-blocks/issues/13) 99 | * Cleanup: Remove custom_blocks method since its not used anymore. This method was for scanning local blocks inside /wp-content/gutenberg-blocks directory 100 | 101 | = 1.1.2 = 102 | * Fix: Fix wrong label in block details [issue #9](https://github.com/front/cloud-blocks/issues/9) 103 | * Fix: Fix network activation issue [issue #11](https://github.com/front/cloud-blocks/issues/11) 104 | * Add: Polish translation. (Thanks to [ajotka](https://github.com/front/cloud-blocks/pull/8)) 105 | * Add: Update counter & label in menu. (Thanks to [ajotka](https://github.com/front/cloud-blocks/pull/10)) 106 | 107 | = 1.1.1 = 108 | * Fix: Update blocks if new version available on the cloud 109 | * Enhancement: Improvement in local block screenshots. The filename can be both screenshot or thumbnail and it could be in blocks root directory or build folder 110 | 111 | 112 | = 1.1.0 = 113 | * Fix: Change array dereferencing in activation hook 114 | * Fix: Show block in installed list even after block removed from Gutenberg Cloud 115 | * Fix: Don't display Installed notice on blocks in Installed tab 116 | * Fix: Search blocks in installed and local blocks 117 | * Add: Listing for local custom blocks, install and delete them (In previous versions, blocks were activated automatically, from now on, you need to explicitly activate/deactivate them in the "Local" tab.) 118 | * Add: Default block screenshot 119 | * Change: Change minimum required php version 120 | * Change: Check for db structure update in upgrader_process_complete hook instead of init 121 | 122 | = 1.0.10 = 123 | * Fix: Fix block js dependency introduced in Gutenberg 4.5.1 124 | 125 | = 1.0.9 = 126 | * Change: Change increase and decrease number of installations of a block 127 | 128 | = 1.0.8 = 129 | * Fix: Fix some issues in previous version release 130 | 131 | = 1.0.7 = 132 | * Change: Private custom blocks now should be under **wp-content/uploads/gutenberg-blocks/** 133 | * Add: Implement UI to upload zip file with custom block [issue #3](https://github.com/front/cloud-blocks/issues/3) 134 | * Fix: Fix a bug about enqueue custom blocks assets [issue #4](https://github.com/front/cloud-blocks/issues/4) 135 | * Fix: Fix an issue with javascript if search query is empty 136 | 137 | = 1.0.6 = 138 | * Add: Implement order for blocks (Latest or Popular) 139 | * Fix: Block counter in popular and latest tabls 140 | * Fix: Display block author 141 | * Change: Blocks homepage url 142 | * Change: If there is no installed blocks, redirect to Popular tab instead of Installed 143 | * Change: Update documentations 144 | 145 | = 1.0.5 = 146 | * Add: Add modal with block info (like themes) [issue #2](https://github.com/front/cloud-blocks/issues/2) 147 | * Fix: Limit enqueue of block styles only to editor or front-end 148 | 149 | = 1.0.4 = 150 | * Fix: Fix translations variable name in javascript files 151 | * Change: Update readme 152 | 153 | = 1.0.3 = 154 | * Change: Update readme 155 | * Add: More docs 156 | 157 | = 1.0.2 = 158 | * Change: Some translation fixes 159 | * Change: Better documentation and screenshot 160 | * Added: Italian translation. (Thanks to [cipo28](https://github.com/front/cloud-blocks/pull/1)) 161 | 162 | = 1.0.1 = 163 | * Fix: is_plugin_active() undefined fix 164 | * Fix: Change strings functions to static 165 | 166 | = 1.0.0 = 167 | * Initial plugin 168 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. 17 | * 18 | * $loader = new \Composer\Autoload\ClassLoader(); 19 | * 20 | * // register classes with namespaces 21 | * $loader->add('Symfony\Component', __DIR__.'/component'); 22 | * $loader->add('Symfony', __DIR__.'/framework'); 23 | * 24 | * // activate the autoloader 25 | * $loader->register(); 26 | * 27 | * // to enable searching the include path (eg. for PEAR packages) 28 | * $loader->setUseIncludePath(true); 29 | * 30 | * In this example, if you try to use a class in the Symfony\Component 31 | * namespace or one of its children (Symfony\Component\Console for instance), 32 | * the autoloader will first look for the class under the component/ 33 | * directory, and it will then fallback to the framework/ directory if not 34 | * found before giving up. 35 | * 36 | * This class is loosely based on the Symfony UniversalClassLoader. 37 | * 38 | * @author Fabien Potencier 39 | * @author Jordi Boggiano 40 | * @see http://www.php-fig.org/psr/psr-0/ 41 | * @see http://www.php-fig.org/psr/psr-4/ 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | private $classMapAuthoritative = false; 57 | private $missingClasses = array(); 58 | private $apcuPrefix; 59 | 60 | public function getPrefixes() 61 | { 62 | if (!empty($this->prefixesPsr0)) { 63 | return call_user_func_array('array_merge', $this->prefixesPsr0); 64 | } 65 | 66 | return array(); 67 | } 68 | 69 | public function getPrefixesPsr4() 70 | { 71 | return $this->prefixDirsPsr4; 72 | } 73 | 74 | public function getFallbackDirs() 75 | { 76 | return $this->fallbackDirsPsr0; 77 | } 78 | 79 | public function getFallbackDirsPsr4() 80 | { 81 | return $this->fallbackDirsPsr4; 82 | } 83 | 84 | public function getClassMap() 85 | { 86 | return $this->classMap; 87 | } 88 | 89 | /** 90 | * @param array $classMap Class to filename map 91 | */ 92 | public function addClassMap(array $classMap) 93 | { 94 | if ($this->classMap) { 95 | $this->classMap = array_merge($this->classMap, $classMap); 96 | } else { 97 | $this->classMap = $classMap; 98 | } 99 | } 100 | 101 | /** 102 | * Registers a set of PSR-0 directories for a given prefix, either 103 | * appending or prepending to the ones previously set for this prefix. 104 | * 105 | * @param string $prefix The prefix 106 | * @param array|string $paths The PSR-0 root directories 107 | * @param bool $prepend Whether to prepend the directories 108 | */ 109 | public function add($prefix, $paths, $prepend = false) 110 | { 111 | if (!$prefix) { 112 | if ($prepend) { 113 | $this->fallbackDirsPsr0 = array_merge( 114 | (array) $paths, 115 | $this->fallbackDirsPsr0 116 | ); 117 | } else { 118 | $this->fallbackDirsPsr0 = array_merge( 119 | $this->fallbackDirsPsr0, 120 | (array) $paths 121 | ); 122 | } 123 | 124 | return; 125 | } 126 | 127 | $first = $prefix[0]; 128 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 129 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 130 | 131 | return; 132 | } 133 | if ($prepend) { 134 | $this->prefixesPsr0[$first][$prefix] = array_merge( 135 | (array) $paths, 136 | $this->prefixesPsr0[$first][$prefix] 137 | ); 138 | } else { 139 | $this->prefixesPsr0[$first][$prefix] = array_merge( 140 | $this->prefixesPsr0[$first][$prefix], 141 | (array) $paths 142 | ); 143 | } 144 | } 145 | 146 | /** 147 | * Registers a set of PSR-4 directories for a given namespace, either 148 | * appending or prepending to the ones previously set for this namespace. 149 | * 150 | * @param string $prefix The prefix/namespace, with trailing '\\' 151 | * @param array|string $paths The PSR-4 base directories 152 | * @param bool $prepend Whether to prepend the directories 153 | * 154 | * @throws \InvalidArgumentException 155 | */ 156 | public function addPsr4($prefix, $paths, $prepend = false) 157 | { 158 | if (!$prefix) { 159 | // Register directories for the root namespace. 160 | if ($prepend) { 161 | $this->fallbackDirsPsr4 = array_merge( 162 | (array) $paths, 163 | $this->fallbackDirsPsr4 164 | ); 165 | } else { 166 | $this->fallbackDirsPsr4 = array_merge( 167 | $this->fallbackDirsPsr4, 168 | (array) $paths 169 | ); 170 | } 171 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 172 | // Register directories for a new namespace. 173 | $length = strlen($prefix); 174 | if ('\\' !== $prefix[$length - 1]) { 175 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 176 | } 177 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 178 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 179 | } elseif ($prepend) { 180 | // Prepend directories for an already registered namespace. 181 | $this->prefixDirsPsr4[$prefix] = array_merge( 182 | (array) $paths, 183 | $this->prefixDirsPsr4[$prefix] 184 | ); 185 | } else { 186 | // Append directories for an already registered namespace. 187 | $this->prefixDirsPsr4[$prefix] = array_merge( 188 | $this->prefixDirsPsr4[$prefix], 189 | (array) $paths 190 | ); 191 | } 192 | } 193 | 194 | /** 195 | * Registers a set of PSR-0 directories for a given prefix, 196 | * replacing any others previously set for this prefix. 197 | * 198 | * @param string $prefix The prefix 199 | * @param array|string $paths The PSR-0 base directories 200 | */ 201 | public function set($prefix, $paths) 202 | { 203 | if (!$prefix) { 204 | $this->fallbackDirsPsr0 = (array) $paths; 205 | } else { 206 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 207 | } 208 | } 209 | 210 | /** 211 | * Registers a set of PSR-4 directories for a given namespace, 212 | * replacing any others previously set for this namespace. 213 | * 214 | * @param string $prefix The prefix/namespace, with trailing '\\' 215 | * @param array|string $paths The PSR-4 base directories 216 | * 217 | * @throws \InvalidArgumentException 218 | */ 219 | public function setPsr4($prefix, $paths) 220 | { 221 | if (!$prefix) { 222 | $this->fallbackDirsPsr4 = (array) $paths; 223 | } else { 224 | $length = strlen($prefix); 225 | if ('\\' !== $prefix[$length - 1]) { 226 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 227 | } 228 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 229 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 230 | } 231 | } 232 | 233 | /** 234 | * Turns on searching the include path for class files. 235 | * 236 | * @param bool $useIncludePath 237 | */ 238 | public function setUseIncludePath($useIncludePath) 239 | { 240 | $this->useIncludePath = $useIncludePath; 241 | } 242 | 243 | /** 244 | * Can be used to check if the autoloader uses the include path to check 245 | * for classes. 246 | * 247 | * @return bool 248 | */ 249 | public function getUseIncludePath() 250 | { 251 | return $this->useIncludePath; 252 | } 253 | 254 | /** 255 | * Turns off searching the prefix and fallback directories for classes 256 | * that have not been registered with the class map. 257 | * 258 | * @param bool $classMapAuthoritative 259 | */ 260 | public function setClassMapAuthoritative($classMapAuthoritative) 261 | { 262 | $this->classMapAuthoritative = $classMapAuthoritative; 263 | } 264 | 265 | /** 266 | * Should class lookup fail if not found in the current class map? 267 | * 268 | * @return bool 269 | */ 270 | public function isClassMapAuthoritative() 271 | { 272 | return $this->classMapAuthoritative; 273 | } 274 | 275 | /** 276 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled. 277 | * 278 | * @param string|null $apcuPrefix 279 | */ 280 | public function setApcuPrefix($apcuPrefix) 281 | { 282 | $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; 283 | } 284 | 285 | /** 286 | * The APCu prefix in use, or null if APCu caching is not enabled. 287 | * 288 | * @return string|null 289 | */ 290 | public function getApcuPrefix() 291 | { 292 | return $this->apcuPrefix; 293 | } 294 | 295 | /** 296 | * Registers this instance as an autoloader. 297 | * 298 | * @param bool $prepend Whether to prepend the autoloader or not 299 | */ 300 | public function register($prepend = false) 301 | { 302 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 303 | } 304 | 305 | /** 306 | * Unregisters this instance as an autoloader. 307 | */ 308 | public function unregister() 309 | { 310 | spl_autoload_unregister(array($this, 'loadClass')); 311 | } 312 | 313 | /** 314 | * Loads the given class or interface. 315 | * 316 | * @param string $class The name of the class 317 | * @return bool|null True if loaded, null otherwise 318 | */ 319 | public function loadClass($class) 320 | { 321 | if ($file = $this->findFile($class)) { 322 | includeFile($file); 323 | 324 | return true; 325 | } 326 | } 327 | 328 | /** 329 | * Finds the path to the file where the class is defined. 330 | * 331 | * @param string $class The name of the class 332 | * 333 | * @return string|false The path if found, false otherwise 334 | */ 335 | public function findFile($class) 336 | { 337 | // class map lookup 338 | if (isset($this->classMap[$class])) { 339 | return $this->classMap[$class]; 340 | } 341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { 342 | return false; 343 | } 344 | if (null !== $this->apcuPrefix) { 345 | $file = apcu_fetch($this->apcuPrefix.$class, $hit); 346 | if ($hit) { 347 | return $file; 348 | } 349 | } 350 | 351 | $file = $this->findFileWithExtension($class, '.php'); 352 | 353 | // Search for Hack files if we are running on HHVM 354 | if (false === $file && defined('HHVM_VERSION')) { 355 | $file = $this->findFileWithExtension($class, '.hh'); 356 | } 357 | 358 | if (null !== $this->apcuPrefix) { 359 | apcu_add($this->apcuPrefix.$class, $file); 360 | } 361 | 362 | if (false === $file) { 363 | // Remember that this class does not exist. 364 | $this->missingClasses[$class] = true; 365 | } 366 | 367 | return $file; 368 | } 369 | 370 | private function findFileWithExtension($class, $ext) 371 | { 372 | // PSR-4 lookup 373 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 374 | 375 | $first = $class[0]; 376 | if (isset($this->prefixLengthsPsr4[$first])) { 377 | $subPath = $class; 378 | while (false !== $lastPos = strrpos($subPath, '\\')) { 379 | $subPath = substr($subPath, 0, $lastPos); 380 | $search = $subPath.'\\'; 381 | if (isset($this->prefixDirsPsr4[$search])) { 382 | foreach ($this->prefixDirsPsr4[$search] as $dir) { 383 | $length = $this->prefixLengthsPsr4[$first][$search]; 384 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 385 | return $file; 386 | } 387 | } 388 | } 389 | } 390 | } 391 | 392 | // PSR-4 fallback dirs 393 | foreach ($this->fallbackDirsPsr4 as $dir) { 394 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 395 | return $file; 396 | } 397 | } 398 | 399 | // PSR-0 lookup 400 | if (false !== $pos = strrpos($class, '\\')) { 401 | // namespaced class name 402 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 403 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 404 | } else { 405 | // PEAR-like class name 406 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 407 | } 408 | 409 | if (isset($this->prefixesPsr0[$first])) { 410 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 411 | if (0 === strpos($class, $prefix)) { 412 | foreach ($dirs as $dir) { 413 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 414 | return $file; 415 | } 416 | } 417 | } 418 | } 419 | } 420 | 421 | // PSR-0 fallback dirs 422 | foreach ($this->fallbackDirsPsr0 as $dir) { 423 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 424 | return $file; 425 | } 426 | } 427 | 428 | // PSR-0 include paths. 429 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 430 | return $file; 431 | } 432 | 433 | return false; 434 | } 435 | } 436 | 437 | /** 438 | * Scope isolated include. 439 | * 440 | * Prevents access to $this/self from included files. 441 | */ 442 | function includeFile($file) 443 | { 444 | include $file; 445 | } 446 | -------------------------------------------------------------------------------- /vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) Nils Adermann, Jordi Boggiano 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | $baseDir . '/core/Activator.php', 10 | 'CloudBlocks\\Blocks\\Blocks' => $baseDir . '/core/Blocks/Blocks.php', 11 | 'CloudBlocks\\Blocks\\Explore' => $baseDir . '/core/Blocks/Explore.php', 12 | 'CloudBlocks\\Blocks\\Options' => $baseDir . '/core/Blocks/Options.php', 13 | 'CloudBlocks\\CloudBlocks' => $baseDir . '/core/CloudBlocks.php', 14 | 'CloudBlocks\\Settings\\Tools' => $baseDir . '/core/Settings/Tools.php', 15 | 'CloudBlocks\\Settings\\Translations' => $baseDir . '/core/Settings/Translations.php', 16 | 'SevenFields\\Bootstrap\\Bootstrap' => $vendorDir . '/foadyousefi/seven-fields/src/Bootstrap/Bootstrap.php', 17 | 'SevenFields\\Container\\Container' => $vendorDir . '/foadyousefi/seven-fields/src/Container/Container.php', 18 | 'SevenFields\\Fields\\Checkbox' => $vendorDir . '/foadyousefi/seven-fields/src/Fields/Checkbox.php', 19 | 'SevenFields\\Fields\\Fields' => $vendorDir . '/foadyousefi/seven-fields/src/Fields/Fields.php', 20 | 'SevenFields\\Fields\\Header' => $vendorDir . '/foadyousefi/seven-fields/src/Fields/Header.php', 21 | 'SevenFields\\Fields\\Html' => $vendorDir . '/foadyousefi/seven-fields/src/Fields/Html.php', 22 | 'SevenFields\\Fields\\Multiselect' => $vendorDir . '/foadyousefi/seven-fields/src/Fields/Multiselect.php', 23 | 'SevenFields\\Fields\\Select' => $vendorDir . '/foadyousefi/seven-fields/src/Fields/Select.php', 24 | 'SevenFields\\Fields\\Text' => $vendorDir . '/foadyousefi/seven-fields/src/Fields/Text.php', 25 | 'SevenFields\\Fields\\Textarea' => $vendorDir . '/foadyousefi/seven-fields/src/Fields/Textarea.php', 26 | ); 27 | -------------------------------------------------------------------------------- /vendor/composer/autoload_namespaces.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/foadyousefi/seven-fields/src'), 10 | 'CloudBlocks\\' => array($baseDir . '/core'), 11 | ); 12 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); 27 | if ($useStaticLoader) { 28 | require_once __DIR__ . '/autoload_static.php'; 29 | 30 | call_user_func(\Composer\Autoload\ComposerStaticInit2948bd210a8be025dfcec89b6ee15fb8::getInitializer($loader)); 31 | } else { 32 | $map = require __DIR__ . '/autoload_namespaces.php'; 33 | foreach ($map as $namespace => $path) { 34 | $loader->set($namespace, $path); 35 | } 36 | 37 | $map = require __DIR__ . '/autoload_psr4.php'; 38 | foreach ($map as $namespace => $path) { 39 | $loader->setPsr4($namespace, $path); 40 | } 41 | 42 | $classMap = require __DIR__ . '/autoload_classmap.php'; 43 | if ($classMap) { 44 | $loader->addClassMap($classMap); 45 | } 46 | } 47 | 48 | $loader->register(true); 49 | 50 | return $loader; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | 11 | array ( 12 | 'SevenFields\\' => 12, 13 | ), 14 | 'C' => 15 | array ( 16 | 'CloudBlocks\\' => 12, 17 | ), 18 | ); 19 | 20 | public static $prefixDirsPsr4 = array ( 21 | 'SevenFields\\' => 22 | array ( 23 | 0 => __DIR__ . '/..' . '/foadyousefi/seven-fields/src', 24 | ), 25 | 'CloudBlocks\\' => 26 | array ( 27 | 0 => __DIR__ . '/../..' . '/core', 28 | ), 29 | ); 30 | 31 | public static $classMap = array ( 32 | 'CloudBlocks\\Activator' => __DIR__ . '/../..' . '/core/Activator.php', 33 | 'CloudBlocks\\Blocks\\Blocks' => __DIR__ . '/../..' . '/core/Blocks/Blocks.php', 34 | 'CloudBlocks\\Blocks\\Explore' => __DIR__ . '/../..' . '/core/Blocks/Explore.php', 35 | 'CloudBlocks\\Blocks\\Options' => __DIR__ . '/../..' . '/core/Blocks/Options.php', 36 | 'CloudBlocks\\CloudBlocks' => __DIR__ . '/../..' . '/core/CloudBlocks.php', 37 | 'CloudBlocks\\Settings\\Tools' => __DIR__ . '/../..' . '/core/Settings/Tools.php', 38 | 'CloudBlocks\\Settings\\Translations' => __DIR__ . '/../..' . '/core/Settings/Translations.php', 39 | 'SevenFields\\Bootstrap\\Bootstrap' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Bootstrap/Bootstrap.php', 40 | 'SevenFields\\Container\\Container' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Container/Container.php', 41 | 'SevenFields\\Fields\\Checkbox' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Fields/Checkbox.php', 42 | 'SevenFields\\Fields\\Fields' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Fields/Fields.php', 43 | 'SevenFields\\Fields\\Header' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Fields/Header.php', 44 | 'SevenFields\\Fields\\Html' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Fields/Html.php', 45 | 'SevenFields\\Fields\\Multiselect' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Fields/Multiselect.php', 46 | 'SevenFields\\Fields\\Select' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Fields/Select.php', 47 | 'SevenFields\\Fields\\Text' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Fields/Text.php', 48 | 'SevenFields\\Fields\\Textarea' => __DIR__ . '/..' . '/foadyousefi/seven-fields/src/Fields/Textarea.php', 49 | ); 50 | 51 | public static function getInitializer(ClassLoader $loader) 52 | { 53 | return \Closure::bind(function () use ($loader) { 54 | $loader->prefixLengthsPsr4 = ComposerStaticInit2948bd210a8be025dfcec89b6ee15fb8::$prefixLengthsPsr4; 55 | $loader->prefixDirsPsr4 = ComposerStaticInit2948bd210a8be025dfcec89b6ee15fb8::$prefixDirsPsr4; 56 | $loader->classMap = ComposerStaticInit2948bd210a8be025dfcec89b6ee15fb8::$classMap; 57 | 58 | }, null, ClassLoader::class); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "foadyousefi/seven-fields", 4 | "version": "dev-master", 5 | "version_normalized": "9999999-dev", 6 | "source": { 7 | "type": "git", 8 | "url": "https://github.com/foadyousefi/seven-fields.git", 9 | "reference": "3ac7be69dc5b30138ae289002d18b974ea237d52" 10 | }, 11 | "dist": { 12 | "type": "zip", 13 | "url": "https://api.github.com/repos/foadyousefi/seven-fields/zipball/3ac7be69dc5b30138ae289002d18b974ea237d52", 14 | "reference": "3ac7be69dc5b30138ae289002d18b974ea237d52", 15 | "shasum": "" 16 | }, 17 | "require": { 18 | "php": ">=5.3" 19 | }, 20 | "time": "2018-10-02T07:34:15+00:00", 21 | "type": "library", 22 | "installation-source": "source", 23 | "autoload": { 24 | "psr-4": { 25 | "SevenFields\\": "src/" 26 | } 27 | }, 28 | "notification-url": "https://packagist.org/downloads/", 29 | "license": [ 30 | "GPL-2.0" 31 | ], 32 | "authors": [ 33 | { 34 | "name": "Foad Yousefi", 35 | "email": "foadyousefi@gmail.com", 36 | "homepage": "https://7km.co/" 37 | } 38 | ], 39 | "description": "WordPress developer-friendly option pages with custom fields.", 40 | "homepage": "https://7km.co/" 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /vendor/foadyousefi/seven-fields/README.md: -------------------------------------------------------------------------------- 1 | # Seven-Fields 2 | 3 | ### About 4 | For one of my projects that needs some settings, I searched to find a library who does this for me. I found Carbon Fields, its nice and relativaly easy to use and most important, could be installed via composer. 5 | 6 | But it has its limitations. Non of the fields types had description (at least when I used it). Also the function for retriving options valie from database, is loading after **init** action, but what if I need to access data before init? Well, I need to write my function. And also field types was a bit limited. 7 | 8 | So decided to write my own and after finishing, thought why not to open source it so other can benifit. 9 | 10 | ### Supported Fields 11 | - Checkbox 12 | - Header 13 | - Raw html 14 | - Multiselect 15 | - Select 16 | - Textfield 17 | - Textarea 18 | 19 | More fields will be added later, but til them, don't hesitate to ask for features and more fields by opening new issue. 20 | 21 | ### How to use? 22 | 23 | 1- In your plugin or theme directory, run 24 | `composer require foadyousefi/seven-fields` 25 | 26 | 2- In your functions.php or your plugin write: 27 | ``` 28 | use SevenFields\Fields\Fields; 29 | use SevenFields\Container\Container; 30 | 31 | add_action( 'admin_menu', 'setting_pages_init' ); 32 | function setting_pages_init() { 33 | Container::make( 'Menu title', 'menu-slug' ) 34 | ->add_fields( 'add_fields_to_the_page' ); 35 | } 36 | 37 | function add_fields_to_the_page() { 38 | Fields::add('header', null, 'This is header' ); 39 | Fields::add('text', 'example_text_field', 'This is text field', 'And this is description' ); 40 | Fields::add( 'checkbox', 'example_checkbox', 'Checkbox label', 'And description' ); 41 | Fields::add( 'textarea', 'example_text_area', 'Textarea example', 'And description. New line in description with bold text.' ); 42 | 43 | } 44 | ``` 45 | 46 | ### How to read options? 47 | 48 | To read options from database, you can somply use wordpress [`get_option()`](https://developer.wordpress.org/reference/functions/get_option/) function by passing the optoin name and optional default value. like so: 49 | 50 | ``` 51 | get_option( 'example_text_field', 'lorem ipsum' ) 52 | ``` 53 | 54 | 55 | I will try to update README and describe all possible options. 56 | -------------------------------------------------------------------------------- /vendor/foadyousefi/seven-fields/VERSION: -------------------------------------------------------------------------------- 1 | 1.0.0 -------------------------------------------------------------------------------- /vendor/foadyousefi/seven-fields/assets/css/styles.css: -------------------------------------------------------------------------------- 1 | .seven-form-wraper .seven-field { 2 | position: relative; 3 | padding: 14px 12px 15px; 4 | background: #fff; 5 | border-width: 1px 1px 0 0; 6 | border-style: solid; 7 | border-color: #e5e5e5; } 8 | .seven-form-wraper .seven-field h3 { 9 | padding: 0; 10 | font-size: 28px; 11 | margin: 0; 12 | line-height: 1; 13 | font-weight: 200; } 14 | .seven-form-wraper .seven-field .label { 15 | font-weight: 600; 16 | margin-bottom: 10px; } 17 | .seven-form-wraper .seven-field.text-field input, 18 | .seven-form-wraper .seven-field.textarea textarea { 19 | display: block; 20 | width: 100%; 21 | margin-bottom: 10px; } 22 | .seven-form-wraper .seven-field .desc { 23 | color: #888; } 24 | 25 | .seven-form-wraper .form-actions { 26 | flex: 1; 27 | margin-left: 10px; } 28 | -------------------------------------------------------------------------------- /vendor/foadyousefi/seven-fields/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foadyousefi/seven-fields", 3 | "description": "WordPress developer-friendly option pages with custom fields.", 4 | "license": "GPL-2.0", 5 | "homepage": "https://7km.co/", 6 | "authors": [ 7 | { 8 | "name": "Foad Yousefi", 9 | "email": "foadyousefi@gmail.com", 10 | "homepage": "https://7km.co/" 11 | } 12 | ], 13 | "support": { 14 | "source": "https://github.com/7kmCo/seven-fields", 15 | "docs": "https://github.com/7kmCo/seven-fields/wiki/", 16 | "issues": "https://github.com/7kmCo/seven-fields/issues" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "SevenFields\\": "src/" 21 | } 22 | }, 23 | "minimum-stability": "dev", 24 | "require": { 25 | "php": ">=5.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vendor/foadyousefi/seven-fields/config.php: -------------------------------------------------------------------------------- 1 | page_title = $page_title; 70 | $this->menu_slug = isset( $menu_slug ) ? $menu_slug : str_replace(' ','-', strtolower( $page_title ) ); 71 | $this->options_group = str_replace('-','_', $this->menu_slug ) . '_options'; 72 | $this->options_name = str_replace('-','_', $this->menu_slug ); 73 | } 74 | 75 | /** 76 | * Add options menu or sub-menu page. 77 | * 78 | * @since 0.1.0 79 | * @param 80 | * @return 81 | */ 82 | public function add_page() { 83 | 84 | if ( $this->parent_slug ) { 85 | add_submenu_page( 86 | $this->parent_slug, 87 | esc_html__( $this->page_title, 'seven-fields' ), 88 | esc_html__( $this->page_title, 'seven-fields' ), 89 | 'manage_options', 90 | $this->menu_slug, 91 | array( $this, 'page' ) 92 | ); 93 | } else { 94 | add_menu_page( 95 | esc_html__( $this->page_title, 'seven-fields' ), 96 | esc_html__( $this->page_title, 'seven-fields' ), 97 | 'manage_options', 98 | $this->menu_slug, 99 | array( $this, 'page' ), 100 | $this->icon, 101 | $this->position 102 | ); 103 | } 104 | return $this; 105 | } 106 | 107 | /** 108 | * Add options menu or sub-menu page. 109 | * 110 | * @since 0.1.0 111 | * @param 112 | * @return 113 | */ 114 | public function set_parent( $parent ) { 115 | $this->parent_slug = $parent; 116 | return $this; 117 | } 118 | 119 | /** 120 | * Set page icon. 121 | * 122 | * @since 0.1.0 123 | * @param 124 | * @return 125 | */ 126 | public function set_icon( $icon ) { 127 | $this->icon = $icon; 128 | return $this; 129 | } 130 | 131 | /** 132 | * Disable form actions and output the page as plain html page. 133 | * 134 | * @since 0.1.0 135 | * @param 136 | * @return 137 | */ 138 | public function plain_page() { 139 | $this->plain_page = true; 140 | return $this; 141 | } 142 | 143 | /** 144 | * Set page menu position. 145 | * 146 | * @since 0.1.0 147 | * @param 148 | * @return 149 | */ 150 | public function set_menu_position( $position ) { 151 | $this->position = $position; 152 | return $this; 153 | } 154 | 155 | public function add_fields( $callback ) { 156 | if ( isset( $this->parent_slug ) ) { 157 | $this->options_group = str_replace('-','_', strtolower( $this->parent_slug ) ) . '_options'; 158 | $this->options_name = str_replace('-','_', strtolower( $this->parent_slug ) ); 159 | } 160 | $this->fields_callback = $callback; 161 | 162 | $this->add_page(); 163 | return $this; 164 | } 165 | 166 | /** 167 | * Settings page output. 168 | * 169 | * @since 0.1.0 170 | * @param 171 | * @return 172 | */ 173 | public function page() { 174 | ?> 175 |
176 |

page_title, 'seven-fields' ); ?>

177 | plain_page) { 178 | call_user_func( $this->fields_callback ); 179 | } else { ?> 180 |
181 |
182 |
183 | 184 |
185 |
186 | options_group, $this->options_name ); 189 | call_user_func( $this->fields_callback ); 190 | ?> 191 |
192 |
193 | 194 |
195 |
196 |

197 |
198 | 199 |
200 | 201 | 202 |
203 |
204 |
205 |
206 |
207 | 208 |
209 |
210 |
211 |
212 | field_html(); 38 | } 39 | 40 | /** 41 | * Get field value, so we can use it to show current value. 42 | * 43 | * @since 0.1.0 44 | * @param 45 | * @return boolean $field_value 46 | */ 47 | public static function get_value() { 48 | return get_option( self::$name, false ); 49 | } 50 | 51 | /** 52 | * Set field name attr. 53 | * 54 | * @since 0.1.0 55 | * @param 56 | * @return string $input_name 57 | */ 58 | public static function input_name() { 59 | $options_name = parent::$options_name; 60 | return $options_name . '[' . self::$name . ']'; 61 | } 62 | 63 | /** 64 | * And the actual output markup of the field. 65 | * 66 | * @since 0.1.0 67 | * @param 68 | * @return 69 | */ 70 | public function field_html() { 71 | ?> 72 |
73 |
74 | 80 |
81 | field_html(); 30 | } 31 | 32 | /** 33 | * And the actual output markup of the field. 34 | * 35 | * @since 0.1.0 36 | * @param 37 | * @return 38 | */ 39 | public function field_html() { 40 | ?> 41 |
42 |

43 | 44 |
45 | field_html(); 30 | } 31 | 32 | /** 33 | * And the actual output markup of the field. 34 | * 35 | * @since 0.1.0 36 | * @param 37 | * @return 38 | */ 39 | public function field_html() { 40 | ?> 41 |
42 |

43 | 44 |
45 | field_html(); 45 | } 46 | 47 | /** 48 | * Get field value, so we can use it to show current value. 49 | * 50 | * @since 0.1.0 51 | * @param 52 | * @return array $field_value 53 | */ 54 | public static function get_value() { 55 | return get_option( self::$name, null ); 56 | } 57 | 58 | /** 59 | * Set field name attr. 60 | * 61 | * @since 0.1.0 62 | * @param 63 | * @return string $field_name 64 | */ 65 | public static function input_name() { 66 | $options_name = parent::$options_name; 67 | return $options_name . '[' . self::$name . ']'; 68 | } 69 | 70 | /** 71 | * And the actual output markup of the field. 72 | * 73 | * @since 0.1.0 74 | * @param 75 | * @return 76 | */ 77 | public function field_html() { 78 | ?> 79 |
80 |
81 |
82 | $value) { 84 | ?> 85 |

86 | 92 |

93 | 96 |
97 | 98 |
99 | field_html(); 42 | } 43 | 44 | /** 45 | * Get field value, so we can use it to show current value. 46 | * 47 | * @since 0.1.0 48 | * @param 49 | * @return string $field_value 50 | */ 51 | public static function get_value() { 52 | return get_option( self::$name, null ); 53 | } 54 | 55 | /** 56 | * Set field name attr. 57 | * 58 | * @since 0.1.0 59 | * @param 60 | * @return string $field_name 61 | */ 62 | public static function input_name() { 63 | $options_name = parent::$options_name; 64 | return $options_name . '[' . self::$name . ']'; 65 | } 66 | 67 | public function field_html() { 68 | ?> 69 |
70 |
71 | 79 | 80 |
81 | field_html(); 38 | } 39 | 40 | /** 41 | * Get field value, so we can use it to show current value. 42 | * 43 | * @since 0.1.0 44 | * @param 45 | * @return string $field_value 46 | */ 47 | public static function get_value() { 48 | return get_option( self::$name, null ); 49 | } 50 | 51 | /** 52 | * Set field name attr. 53 | * 54 | * @since 0.1.0 55 | * @param 56 | * @return string $field_name 57 | */ 58 | public static function input_name() { 59 | $options_name = parent::$options_name; 60 | return $options_name . '[' . self::$name . ']'; 61 | } 62 | 63 | /** 64 | * And the actual output markup of the field. 65 | * 66 | * @since 0.1.0 67 | * @param 68 | * @return 69 | */ 70 | public function field_html() { 71 | ?> 72 |
73 |
74 | 76 | 77 |
78 | field_html(); 39 | } 40 | 41 | /** 42 | * Get field value, so we can use it to show current value. 43 | * 44 | * @since 0.1.0 45 | * @param 46 | * @return string $field_value 47 | */ 48 | public static function get_value() { 49 | return get_option( self::$name, null ); 50 | } 51 | 52 | /** 53 | * Set field name attr. 54 | * 55 | * @since 0.1.0 56 | * @param 57 | * @return string $field_name 58 | */ 59 | public static function input_name() { 60 | $options_name = parent::$options_name; 61 | return $options_name . '[' . self::$name . ']'; 62 | } 63 | 64 | /** 65 | * And the actual output markup of the field. 66 | * 67 | * @since 0.1.0 68 | * @param 69 | * @return 70 | */ 71 | public function field_html() { 72 | ?> 73 |
74 |
75 | 78 | 79 |
80 |