-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create an API for defining blocks in the editor. #104
Comments
Here are things I think the API should do/have:
Addendum ( Block Types should most likely be registered server side and exposed to the client. ) |
Related controls discussion: #16 Taking a few of the current mockups as a basis, I've identified some/all of the pieces a developer should expect to be able to implement:
Below are a few of my early prototypes which include rough implementations of some or all of these requirements:
Given discussion at aduth/wp-block#1, I've also been wondering if we could optionally / alternatively support server-side block registration options, with the following goals in mind:
We could look to Shortcake and JS Widgets for inspiration on implementing / consolidating server-side registration if it's a path we want to pursue (cc @westonruter @mattheu @danielbachhuber )
Less obvious, but if we decide to add a new syntax for blocks, we'll also want to consider how to add backwards compatibility support for e.g. captioned images (currently shortcode) which should either be supported by or transparently upgraded to the new recommended block. This might need to be a separate issue. |
Getting into a little more detail, for both block and inline controls, we'll have the following requirements (some assuming we follow proposed block comment syntax):
|
Just to note here that JS Widgets 0.4 was recently released and it includes full integration with Shortcake so that all widgets defined as “JS widgets” are automatically also available as Shortcake post elements (content blocks). Likewise it introduces icons for widgets (current Dashicons). The server-side registration ensures that that the widgets (blocks) can be exposed in the REST API and that the widget instance data is guaranteed to be JSON-representable so that the data can be manipulated directly with JS (see WP-CORE#35574, WP-CORE#33507). The widget also then defines the interface for manipulating the data, sanitizing the data, and rendering the data with PHP. The shortcode on the other hand only addresses the last piece, the rendering of the data. The Shortcake plugin was developed to implement the shortcode UI which essentially is a JS-driven version of what widgets historically handled with PHP ( |
We should probably not tackle nested blocks for the editor focus. This will absolutely become necessary for the customization focus, but probably best as something to keep in mind but not work on. Incidentally you pointed out an error in the mockups. Yes, you should be able to format quotes. The omission of controls was in error. Here's an updated mockup:
Absolutely. Headings probably shouldn't have any formatting at all. I'm sure there will be other blocks with unique requirements. |
Are there plans for what to do with oEmbed content like if someone posts a link to a YT in a paragraph? I'd think it's safer to
|
Some discussion here: #81 (comment) See also #24 (comment) |
I was going to mention that in complementing discussion in #81, it would be nice to support blocks registering as being associated with a particular oEmbed URL pattern, such as to allow a YouTube block to enable the user to configure features like start time and autoplay. However, in looking at a few examples, it's not commonly supported to customize the embedded URL to affect these changes. In YouTube's case, you'd have to modify the markup of the embedded frame returned, or for Vimeo passing as arguments to the oEmbed request itself. Which is to say, neither of these services would allow you to control their embed behavior by the URL we'd expect to be saved in post content. |
Stepping back for a moment, I thought it could be useful to outline some requirements of a block API for both a block implementer (plugin author) and the editor itself, as well as some ideas I've been exploring as conclusions of these requirements. RequirementsPlugin Author:At it's most basic, the idea of a user inserting a block is...
There are a few more nuanced requirements or desires, a few highlighted here:
Editor:Ideally, the editor...
Conclusions / Ideas:Block Demarcation SyntaxThere have been some explorations of a block demarcation syntax, such as that in the "Coda" section of the original technical overview post. Here it was proposed to use comments to mark the bounds of a block: <!-- wp:image -->
<figure>
<img src="/">
<figcaption>A picture is worth a thousand words</figcaption>
</figure>
<!-- /wp --> The post grammar explorations took this further to consider encoding some attributes within the comment syntax itself: <!-- wp:image src:"/" caption:"A picture is worth a thousand words" -->
<figure>
<img src="/">
<figcaption>A picture is worth a thousand words</figcaption>
</figure>
<!-- /wp --> The idea of serializing a block's state entirely within the comment is nice because it can be easily parsed and exposed, even server-side and made available through the REST API. It also enables a block to be more easily rendered because the block's rendering logic becomes a function of its current state (if you're familiar with React paradigms, much like the idea of "components" and "props"). It lessens worries of markup becoming becoming out of sync because we treat the encoded state as the ultimate source of truth, we know what to expect and, if we find that the markup differs, we can provide fallbacks. Finally, it avoids the plugin author needing to manually determine their own block's state by parsing the DOM or traversing an AST. The most obvious downside is the amount of duplication that occurs between the attributes and the markup itself. I think there are a few options:
To this last point, I think an idea that @danielbachhuber had considered for secret data (aduth/wp-block#2 (comment)) could be useful for all cases. If the state of a block is only truly necessary in its raw form in the context of the editor and from the REST API, it seems reasonable to store this elsewhere as post meta. So the markup becomes: <!-- wp:image 841 -->
<figure>
<img src="/">
<figcaption>A picture is worth a thousand words</figcaption>
</figure>
<!-- /wp --> Where Edit: Maybe this becomes simpler if the type itself is moved to post meta, where comments are generalized e.g. Block SchemasWhile the above syntax can enable us to more easily make the state of a block available to other clients such as mobile apps, it's still not sufficient to enable them to present any sort of editable form. To support this and inspired by previous discussion in aduth/wp-block#1, there may be value in allowing the minimal representation of a block to be defined as a schema server-side. register_block( 'image', [
'schema' => [
'type' => 'object',
'properties' => [
'src' => [ 'type' => 'string' ],
'caption' => [ 'type' => 'string' ]
]
]
] ); The benefits here would be:
Componentization of Complex BehaviorsWhile it's yet to be decided how far we take the idea of React's "UI a function of state", it leads naturally to componentizing not only blocks, but common behaviors between blocks. In the current multi-instance prototype, @youknowriad has applied this as far as toolbars being the responsibility of a block to render, which is not as difficult as it seems when masked as a simple To my own earlier example, if one needed to control complex editable behaviors such as allowable markup, these could act as arguments (props) to a shared editable interface. Thinking more concretely and permitting the exploration of React's JSX syntax, a blocks editor render logic could amount to roughly: function ImageBlock( state, onChange ) {
return (
<figure>
<Toolbar />
<Media
src={ state.src }
onChange={ ( src ) => onChange( { src } ) } />
<Editable
inline
allowedTags={ [ 'strong', 'em', 'a' ] }
value={ state.caption }
onChange=( ( caption ) => onChange( { caption } ) ) />
</figure>
);
} |
Thanks @aduth This is really a great summary of the block API needs.
I just have some concerns regarding this. I agree it's ideal if we could limit the block API to the current block itself but I think it's not always possible. How do you think switching block types (we have this on the current prototypes) could work without knowledge about the block types to be switched to/from? Do you imagine a block abstraction like block category or something? The same concerns could apply while "merging" blocks, merging happens if we hit backspace at the beginning of a block. |
@youknowriad AFAIK the oEmbed has similar problems currently. Surely that is something for another issue? Perhaps one referencing this one. |
What happens when the raw editor is used to modify the HTML? In the example of an image that has a postmeta reference containing the src, it will no longer match if I type over the HTML src tag to show a different image. Is there a way to recover from that sort of thing? Or what about typing over the figure tag to make it a paragraph? Or mangling the quotes or brackets? |
@youknowriad makes a good point. There needs to be logic somewhere to transform a paragraph (or a collection of paragraphs and lines with line breaks) into a list and back. Atm the single prototype handles this by passing the node, and the block handles the transformation to and from this "base" state. Similarly a block such as a block quote or a custom section block will need to be able to wrap a (collection of) blocks and unwrap them again. |
@youknowriad This is good to raise, and is indeed an inevitable interaction between blocks. With the ideal in mind, we could at least position this such that a block defines what it can be initialized from (as an explicit opt-in to the behavior) rather than what it can be transformed to.
@joyously Yes, this could be a problem if we move state of a block out of the markup, because while we've significantly improved developer experience of block implementer by removing the concern of parsing state, the implications are that edits can only be performed on the state data directly, never on the resulting markup. These scenarios are easy enough to detect, if we find that the markup differs from what we'd expect given the current state. In these cases we may be forced to downgrade to a more generic block, i.e. editing |
Another possible UX could be that the block detects that its markup is different from what it would generate and asks the user what to do (it doesn't have to be able to parse the markup, it can just diff it with the current output). Something like, "The HTML of this block has been manually modified. Do you want to convert this into an HTML block or restore the last version of this block before it was modified?" |
This is pretty much exactly what Matt proposed very early on. He called it an I know what I'm doing block:
|
@aduth another problem with storing the block state in postmeta is that the state is then no longer tracked in post revisions with the content. Maybe this would be solved when revisions support is added for postmeta (#20564), or maybe also there would to be potential for the content and the corresponding postmeta to get out of sync. |
Ah, thanks so much for raising that @westonruter , that's a very good point and could have bitten us hard later down the road 😬 Thanks also for the link to the ticket. Reading through and perusing the latest plugin code, it appears to be a good fit for what we'd need in tracking meta with each revision (cc @adamsilverstein as owner). At worst and while certainly not ideal, storing state in its serialized form in the comment itself doesn't seem out of the question. Doing so would sacrifice some of the benefits, namely: sending more to the front-end than necessary and losing ability to store secrets. |
Few problems with this approach:
As far as I see most blocks in a post will be (big) chunks of HTML. They will only have one state (i.e. will be stateless) and have no settings. As HTML they are "ready to go" and will not need parsing or rendering. The "block state" would be useless for them. On the other hand this is a good idea for "dynamic blocks". In the current editor the "state" of dynamic blocks (a.k.a. wpviews) is the text string used to create them (usually a shortcode or URL). This works pretty well in the HTML editor too as the actual block content is removed when switching to it and replaced with the "block state", then the "block" is rendered again on switching back to visual. Of course this can be extended for use with the block demarcation. |
At the point I'm not sure a JSON field in MySQL is such a good option (although it's query-able), but for some systems that live on top of WordPress there are already a litany of fields jammed into the post meta table(s) |
Another problem I think we've overlooked 'til now is that while we've been discussing options for universal understanding between browser and server of block state and state shape, we've not put the same consideration toward generating block markup. So even if the server or mobile app is able to understand and perhaps even update the raw state values, as of now we have no consensus on how to update the markup accordingly. As an addendum to my earlier comment, it should be a requirement of the editor that a client is able to update its markup in response to user input without a round-trip to the server. Off the top of my head, we may have a couple options, neither of which I'm particularly happy with:
Does anyone have ideas for how we might tackle this? |
In an ideal world, the client and server would be able to render a block. But as you note, this is really only feasible if both the server and the client are running the same language (e.g. JavaScript)… or if there is a sufficiently powerful templating language that has implementations in both JS and PHP, and I don't think Mustache is powerful enough. I'm inclined think it is not reasonable to expect that the arbitrarily-complex rendering logic on the frontend (in PHP) to be able to be run on the client by JavaScript (in the editor) as well. I think the approach that Shortcake took by rendering shortcodes on the server to be a reasonable baseline pattern to follow with rendering blocks in the editor. Otherwise, a block could provide a basic rough/ |
I ran into this same challenge when I was exploring these ideas at the end of last year. Mostly I had the same thoughts as you @aduth and @westonruter: shared markup language (that's probably insufficient), or server-rendered only (makes offline impossible, slow to update, and sucks for poor connections). I was only able to come up with two conclusions of my own:
|
Do you have anything specific in mind for an approach here? I've been thinking about this a bit and was curious if we could either treat the block effectively as an iframe via WebView (with some communication to the parent native context), or generate a scaffolded form from a block's schema and, upon change, execute the JavaScript for generating markup given a particular set of block attributes. This thinking might be a little naive since I've not worked much in a native environment. Those more familiar could indulge us with possible gotchas, particularly around loading scripts from a user's own site. |
To throw in my two cents: I agree with azaozz's sentiments. To me the editor should only be concerned with manipulating the Proposed Flow:
On the "secret/private" data idea: This type of data should/would exist only on "dynamic blocks" of content. We should make use of the shortcodes API already present in WordPress to handle that kind of stuff and improve that experience via iseulde's idea. Any reference data that needs to be used would be accessed via the shortcode/resource-id to prevent the sensitive data from being displayed in the actual markup publicly. Block Registry/Definition API: The API for defining/registering blocks should be very simple and only be concerned with defining/registering. As blocks are registered there should be someway for TinyMCE to pull data from the registered blocks and add that to the interface for the editor. The registering of blocks could happen server side, and could be pulled into the JS realm when the editor is being initialized. It could also happen client side and forego PHP, however the more I think about it the less I like this approach. There should probably be an association between a block and its controls, so that TinyMCE can dynamically generate the appropriate controls of a selected block based on the block types registered to the editor. Server vs Client: I do not see any benefit to trying to have the server render a block via static state, that should be handled via JavaScript. The way in which WordPress interacts with PHP/HTTP is stateless. The initial render and the previously saved output of the editor are one in the same. Adding an extra layer where PHP is rendering static state data as HTML seems like an unnecessary step. Use the server to serve what is already saved and let the client interpret the saved Environment:
This is basically what TinyMCE does and although I agree it is fragile, it is also probably the most practical approach moving forward. I believe digging into the flexibility of TinyMCE to enable it to understand blocks properly is probably more important than worrying about rendering state to markup. A state -> markup system can always be created further down the road if it is ever considered that TinyMCE won't be used anymore.
Plugin X's special image block type could be registered to expose data that could be used in a non browser environment. The HTML could be parsed as the state and after it is manipulated then rendered as new HTML in a non browser environment. The exposed block type data could be used in tandem with the HTML in a non browser environment. I think veering away from HTML as the main data format of representing
Make the UI a function of tl;dr: Don't over complicate things and veer too far away from the flow of data WordPress already uses. I think the Block Type Defining API should be server side in PHP. The work on the editor should mainly be focused on making a Single TinyMCE instance understand how to parse, interpret and modify blocks, which are then saved as |
@BE-Webdesign Good stuff, I can always get behind efforts to avoid introducing unnecessary complexity. That said, let's not trivialize making sense of the markup nor working with a DOM. In some ways we've done ourselves a disservice by starting with very simple block types. As far as implementing blocks go, headings and paragraphs are solved problems. The more interesting cases are galleries, contact forms, sliders, maps, repeaters, testimonials, subscribe forms, logo soup, plans comparisons, etc. We should be thinking about all of these block types as we work through the APIs that developers will use to build them.
This is easy for a single element like a paragraph tag, but TinyMCE won't be able to make sense of more complex markup on its own. The step from
Dynamically generated fields don't make for a good UX. When I'm adding a map block, I should see a map, not just a text input.
Kindly I disagree. For anything but the simplest elements, working with and keeping the DOM in sync with our understanding of state quickly becomes very difficult. Introducing conventions or tools is perfectly fine if the cost of becoming familiar with them is strongly negated by an increased sense of overall confidence on the developer's part to create sound implementations. Now a few points to concede on my part:
|
I think for the most part we are on the same page, and I probably am not articulating my ideas too well. My ideas could also be terrible 😄 . I am hoping there can be a way forward that somehow the new block editor can be jump started by
Definitely, and this is what TinyMCE kind of does for us or at least closes that gap a bit. I think it is possible to get TinyMCE to understand "blocks" from the
I was talking about the controls for a block, a map will definitely be there for a map block. So for a "map block" TinyMCE will generate a control that can open a modal or something to switch up the map settings. I am probably not explaining my ideas well 😄 .
You could have React components inside the TinyMCE instance ( or whatever you want really ) to ease the handling of a more complex block. |
This is exactly what the TinyMCE Core team are looking at the moment. We want to be able to support "blocks", "components", "widgets" or whatever to coexist both "in" TinyMCE as well as outside of it. We are trying to get to some sort of 'best of both worlds' approach... but appreciate this project is moving very fast. We're trying to bring the TinyMCE team's ideas in :) |
Experimenting a bit with some of the ideas @aduth had with having a render function and parsing, but without touching the DOM. It would look something like this, where the received content is JSON and h has helpers for this content. Instead of using arrays, you can also use function render( props ) {
return (
[ 'figure', { contenteditable: false },
( ! props.src ?
[ 'div', { onClick: onClick },
[ 'svg', ... ],
[ 'p', 'Pick image' ]
] :
[ 'img', { alt: props.alt, src: props.src } ]
),
[ 'figcaption', {
contenteditable: true,
placeholder: 'Write caption\u2026',
},
...props.caption
]
]
);
}
function getProps( content, h ) {
return {
alt: h.getAttribute( h.find( content, 'img' ), 'alt' ),
src: h.getAttribute( h.find( content, 'img' ), 'src' ),
caption: h.getChildren( h.find( content, 'figcaption' ) )
};
}
function onClick( props, callback ) {
filePicker().then( function( files ) {
...
callback( render( { src: src } ) );
} );
}
registerBlock( {
name: 'image',
...
controls: [ ... ],
render: render,
getProps: getProps
} ); |
Fix paragraph splits on the Paragraph block
* chore(package): update stylelint to version 7.0.0 (#83) * fix: Deprecated `no-missing-eof-newline` rule. Use the new `no-missing-end-of-source-newline` rule instead. (#84) * fix: Fixed font-family-name-quotes` test warning message in `values.js`. (#85) * feat: Add `property-no-unknown` rule. (#86) * Update install instructions to add `--save-dev` * chore(package): update stylelint to version 7.2.0 (#87) * chore(package): update AVA to version 0.16.0 (#88) * chore(package): update eslint-config-stylelint to version 4.0.0 (#89) * chore(package): update ESLint to version 3.0.0 (#90) * feat: Add `at-rule-no-unknown` rule. (#91) * feat: Add `selector-class-pattern` and `selector-id-pattern` rules. (#92) * Prepare 9.0.0 * Merge branch 'master' of github.com:ntwb/stylelint-config-wordpress * feat: Add SCSS preset config (#96) * feat: Add SCSS preset config * fix: Include README.md and scss.js in package.json files list * test: Add initial SCSS tests * Prepare 9.1.0 * Prepare 9.1.1 * refactor: Use ECMAScript 8/2017, use async/await instead of returning a promise and move css code out of tests to individual files * feat: Use ECMAScript 8/2017 * refactor: Use async/await instead of returning a promise and move css code out of tests to individual files * chore(package): update dependencies (#100) https://greenkeeper.io/ * chore: Add NodeJS 7 to Travis & AppVeyor CI test matrix's (#102) * chore(package): update stylelint to version 7.5.0 (#103) * chore: Add NodeJS 7.x changelog note * feat: Add `selector-no-empty` rule. (#104) * chore(package): Update `eslint-plugin-ava` to version 4.0.0 (#105) * fix: SCSS: Dissalow `@debug` at-rules. * fix: SCSS: Add `scss/selector-no-redundant-nesting-selector` rule. * Update ava to the latest version 🚀 (#109) * chore(package): update ava to version 0.17.0 * refactor: Include path to test fixtures https://greenkeeper.io/ * chore(package): update npm-run-all to version 4.0.0 (#111) https://greenkeeper.io/ * Update eslint-config-stylelint to the latest version 🚀 (#110) * chore(package): update eslint-config-stylelint to version 6.0.0 * refactor: Update tests per latest `eslint-config-stylelint` * chore: bump minimum NodeJS requirement to 6.9.1 and drop NodeJS 4.x (#118) * chore: Drop NodeJS from Travis CI * chore: Drop NodeJS from AppVeyor * chore: Bump minimum NodeJS requirement to 6.9.1 * chore: Update remark and remark plugin packages (#120) * Update ava to the latest version 🚀 (#112) * chore(package): update ava to version 0.18.0 https://greenkeeper.io/ * chore: update ava to version 0.19.1 * Updated and removed deprecated stylelint rules for 8.0 (#116) * Updated and removed deprecated stylelint rules * Removed deprecated unit test * chore: Add require NodeJS 6.x LTS changelog note * chore: Update changelog for changes made in #116 * refactor: Switch from AVA to Jest for tests. (#122) * tests: Fix `media-query-list-comma-space-before` tests * refactor: Switch from AVA to Jest for tests. * chore(package): update stylelint to version 7.10.1 (#123) * chore(package): update stylelint-scss to version 1.4.4 (#124) * chore(package): update eslint to version 3.19.0 (#125) * refactor: Switch from eslint-plugin-ava to eslint-plugin-jest. (#126) * refactor: Switch from eslint-plugin-ava to eslint-plugin-jest. * docs: Add changelog entry for switch from eslint-plugin-ava to eslint-plugin-jest * Fixed: Added `stylelint-scss` plugin @if/@else placement rules. (#127) * fix: Ignore proprietary `DXImageTransform.Microsoft` MS filters (#128) * docs: Update CHANEGLOG * Merge branch 'master' of github.com:ntwb/stylelint-config-wordpress * feat: Prepare `10.0.0` release. * fix: Remove stylelint v8 deprecated rule `rule-non-nested-empty-line-before` from SCSS config. (#130) * feat: Prepare `10.0.1` release. * fix: Add `@import` to `ignoreAtRules` option in `at-rule-empty-line-before` rule for SCSS config (#131) * feat: Prepare `10.0.2` release. * chore(package): update eslint-plugin-jest to version 20.0.0 (#134) * chore(package): update jest to version 20.0.0 (#135) * docs: Update docs to reflect the new repository home * docs: Update docs to reflect the new repository home at https://github.com/WordPress-Coding-Standards * chore: Update changelog noting repo location change * fix: Add `declaration-property-unit-whitelist` rule to enforce unitless `line-height` values. (#133) * fix: Include CSS config `at-rule-empty-line-before` options in SCSS config. (#139) * Fix: Allow `px` units in `line-height` values for the `declaration-property-unit-whitelist` rule. (#140) * feat: Prepare `11.0.0` release. * Updated README section links (#141) * chore: Add NodeJS v8 to Travis CI build matrix (#143) * chore: Switch from Node.js "current v7.x branch to v8.x for AppVeyor CI (#145) * chore: Drop Node.js v7.x branch from Travis CI (#146) * refactor: Switch to shared `recommended` config from `eslint-plugin-wordpress` for ESLint configuration. (#147) * refactor: Switch to shared `recommended` config from `eslint-plugin-wordpress` for ESLint configuration. * chore: Use `git://` protocol * chore: Include a commit hash * chore: Update ESLint to version 4.1.0 * chore: Update ESLint to version 4.x * refactor: Update indentation per updated ESLint version 4.x `indent` rule. * chore: Add a `dry-release` npm task (#149) * chore: Move ESLint config from `package.json` to `.eslintrc.json` file. (#152) * chore: Use the latest npm for all Node.js Travis CI jobs * chore: Add npm 5's `package-lock.json` file * chore: Add Greenkeeper support for npm 5.x's `package-lock.json` file. * tests: Add Jest snapshot tests * tests: Update Jest snapshots * chore(package): update stylelint to version 8.0.0 * fix: Add initial support for long comments in headers of WordPress theme `style.css` files. (#151) This change allows for longer comments in themes header: • URLs longer than 80 characters • Descriptions longer than 80 characters • Tags longer than 80 characters Fixes #150. * tests: Add some bbPress Jest snapshot tests. * tests: Update Jest SCSS tests to use SCSS config * tests: Update Jest SCSS test snapshots * tests: Add some BuddyPress Jest snapshot tests. * chore: Use the `runInBand` flag for Jest Travis CI jonbs * tests: Update snapshots * tests: Update tests to account for new rules introduced in `stylelint-config-recommended`. * chore: Add `stylelint-config-recommended` extend base configuration from it. * docs: Update CHANGELOG with `stylelint-config-recommended` changes * docs: Remove the styleguide from the repo. We should have one canonical source of truth and not try to maintain two instances. https://make.wordpress.org/core/handbook/best-practices/coding-standards/css/ * refactor: Use `scss/at-rule-no-unknown` in `scss` shared config. * feat: Prepare `12.0.0` release. * chore(package): update remark-cli to version 4.0.0 * chore: Update `package-lock.json` * chore(package): update remark-preset-lint-recommended to version 3.0.0 * chore: Update `package-lock.json` * fix(package): update stylelint-scss to version 2.0.0 * chore: Update `package-lock.json` * chore: Add `stylelint-find-rules` * chore(package): update stylelint-find-rules to version 1.0.1 Closes #168 * chore: Update package-lock.json * chore: Updated `stylelint` peer dependency version to `^8.0.0`. * chore(package): update jest to version 21.0.0 * chore: Update `package-lock.json` * chore(package): update eslint-plugin-jest to version 21.0.0 * chore: Update `package-lock.json` * tests: Remove Jest snapshots (#176) * docs: Update CHANGELOG * Use toHaveLength() in tests Not only does it check the length of something is exactly a certain integer, it also checks that the length property exists in the first place. Addresses lint issues identified at https://www.bithound.io/github/WordPress-Coding-Standards/stylelint-config-wordpress/e2bbe0d9c867cc95da6de5b3bff2a73742135fb6/files#failing * chore: Remove Greenkeeper lock file configuration from `.travis.yml` * chore: Remove `package-lock.json` * chore: Add `package-lock.json` to `.gitignore` * chore: Add `.npmrc` file to prevent npm creating a `packake-lock.json` file. * chore(package): update jest to version 22.0.0 * chore: update `.editorconfig` per upstream WordPress' `.eitorconfig` See https://core.trac.wordpress.org/browser/trunk/.editorconfig * chore: use tabs for indentaion in `package.json` per WordPress coding standards * chore: use tabs for indentaion in `.eslintrc.json` per WordPress coding standards * chore: use `* text=auto` in `.gitattributes` * chore(package): update remark-cli to version 5.0.0 * chore: standardize Jest tests * chore: add commitlint * chore: bump minimum Nod.js required version to `8.9.3` * test: improved `no-duplicate-selectors` tests * feat: update `stylelint` to `9.1.3` * chore: updated `stylelint-config-recommended` to `2.1.0` * chore: updated: `stylelint-scss` to `2.1.0` * feat: update `selector-pseudo-element-colon-notation` to use `double` * feat: prepare `13.0.0` release * fix(package): update stylelint-scss to version 3.0.0 * docs: update changelog * test: add SCSS tests for _extends_ shared configs This test ensures that the rules included in the _shared configs_ inherited by this SCSS _shared config_ via the `extends` option are in actual fact included. The `stylelint-config-wordpress/scss` shared config _extends_ the `stylelint-config-wordpress` shared config, which in turn _extends_ the `stylelint-config-recommended` shared config. * docs: update changelog * test: standardize invalid tests warnings test name verbiage * test: use Jest snapshots for invalid tests This change simplifies the maintainence of the invalid CSS and SCSS tests * feat: the `/scss` config now extends `stylelint-config-recommended-scss` * feat: update `stylelint` to `9.2.0` * docs: add basic _extends_ shared config references * Update to node 10 in .travis.yml * Drop Node.js v9.x * Update appveyor.yml * chore(package): update @commitlint/cli to version 7.0.0 * chore(package): update @commitlint/config-conventional to version 7.0.1 (#203) Closes #201 * chore(package): update npmpub to version 4.0.1 Closes #204 * feat: update stylelint to `9.5.0` * chore: update ESLint to `5.4.0` * chore: update Jest to `23.5.0` * chore: update `eslint-plugin-jest` to `21.21.0` * chore: update `npmpub` to `4.1.0` * chore: update `npm-run-all` to `4.1.3` * chore: update `stylelint-find-rules` to `1.1.1` * chore: update remark presets: • `remark-preset-lint-consistent` to `2.0.2` • `remark-preset-lint-recommended` to `3.0.2` * feat: update `stylelint-scss` to `3.3.0` * chore: add `npm-package-json-lint` * chore: add `@wordpress/npm-package-json-lint-config` * chore: update `package.json` property order * feat: Prepare `13.1.0` release (#208) * chore(package): update husky to version 1.1.2 (#210) Closes #209 * chore(package): update remark-cli to version 6.0.0 (#211) * chore(package): update eslint-plugin-jest to version 22.0.0 (#212) * Update stylelint-find-rules to the latest version 🚀 (#213) ## The devDependency [stylelint-find-rules](https://github.com/alexilyaev/stylelint-find-rules) was updated from `1.1.1` to `2.0.0`. This version is **not covered** by your **current version range**. If you don’t accept this pull request, your project will work just like it did before. However, you might be missing out on a bunch of new features, fixes and/or performance improvements from the dependency update. * chore(package): update stylelint to version 10.0.1 (#215) Closes #214 * chore: update @commitlint * chore: update `stylelint-config-recommended` to v2.2.0 * chore: update `stylelint-scss` to v3.6.0 * chore: update devDependencies * feat: prepare `14.0.0` release * chore(package): update husky to version 2.2.0 Closes #219 * chore: update `husky.hooks` config in `package.json` * chore(package): update @wordpress/npm-package-json-lint-config to version 2.0.0 * chore(package): update husky to version 3.0.1 Closes #227 * test: fix type in snapshot test * chore(package): update @commitlint/cli to version 8.0.0 * chore(package): update @commitlint/config-conventional to version 8.0.0 * chore(package): update remark-cli to version 7.0.0 * chore(package): update packages to latest versions * chore(package): restore peerDependencies stylelint versions * chore(node): bump minimum Node.JS to LTS version 10.x * ci: use `npm test` to include lint tasks in CI jobs * docs: nocapital_S_dangit * chore(package): update npmpub to version 5.0.0 * fix(package): update stylelint-config-recommended to version 3.0.0 * chore(package): update stylelint to version 11.0.0 * chore: update `peerDependencies` for stylelint 11.0.0 * docs: update changelog * docs: fix stylelint removed compat version * Update stylelint-config-recommended-scss to the latest version 🚀 (#238) * Update eslint to the latest version 🚀 (#233) * chore(package): update eslint to version 6.3.0 * chore: add `ecmaVersion: 2015,` to `parserOptions` ESLint config * docs: update changelog * chore: bump dependencies * chore: add Node.js v12 to Travis CI test matrix, remove 8.x, min 10.x chore: add Node.js v12 to Travis CI test matrix * feat: prepare `15.0.0` release * Merge pull request #241 from WordPress-Coding-Standards/update/find-rules chore: update `stylelint-find-rules` to 2.2.0 * Update npm-package-json-lint to the latest version 🚀 (#242) Update npm-package-json-lint to the latest version 🚀 * Use `@wordpress/scripts` (#231) Use `@wordpress/scripts` * chore: update `stylelint` to 12.0.0 * chore: update `stylelint-scss` to 3.13.0 * chore: update `stylelint-config-recommended-scss` to 4.1.0 * chore: update `husky` to 3.1.0 * chore: update `remark-cli` to 7.0.1 * chore: update `@wordpress/scripts` to 6.0.0 * Fixed: `selector-class-*` regex to account for numerals, case de… (#247) Fixed: `selector-class-*` regex to account for numerals, case detection, and ensure kebab-case * ci: add Windows to Travis CI (#248) ci: add Windows to Travis CI * chore: remove AppVeyor (#249) chore: remove AppVeyor * feat: prepare `16.0.0` release * test: update comment fof scss-invalid test to eslint-jsdoc warnings * feat: prepare `16.0.0` release * fix: npm script temp workaround * Merge pull request #251 from WordPress-Coding-Standards/greenkeeper/@wordpress/scripts-6.1.1 chore(package): update @wordpress/scripts to version 6.1.1 * Revert "fix: npm script temp workaround" This reverts commit e409112e0e8f3965993e3f1b3a6ecc3c8ffdc8e0. * Update husky to the latest version 🚀 (#252) Update husky to the latest version 🚀 * Merge pull request #255 from WordPress-Coding-Standards/greenkeeper/stylelint-13.1.0 Update stylelint to the latest version 🚀 * Merge pull request #254 from WordPress-Coding-Standards/greenkeeper/@wordpress/scripts-7.0.0 Update @wordpress/scripts to the latest version 🚀 * chore(package): update @wordpress/scripts to version 7.1.2 * chore(package): update stylelint-scss to version 3.14.2 * chore(package): update stylelint-config-recommended-scss to version 4.2.0 * chore(package): update husky to version 4.2.3 * chore(package): update @commitlint/cli to version 8.3.5 * chore(package): update @commitlint/config-conventional to version 8.3.4 * Merge pull request #256 from WordPress-Coding-Standards/greenkeeper/remark-cli-8.0.0 Update remark-cli to the latest version 🚀 * Merge pull request #258 from WordPress-Coding-Standards/greenkeeper/remark-preset-lint-recommended-4.0.0 Update remark-preset-lint-recommended to the latest version 🚀 * Merge pull request #257 from WordPress-Coding-Standards/greenkeeper/remark-preset-lint-consistent-3.0.0 Update remark-preset-lint-consistent to the latest version 🚀 * Merge pull request #260 from WordPress-Coding-Standards/greenkeeper/@wordpress/scripts-8.0.1 * Merge pull request #264 from WordPress-Coding-Standards/greenkeeper/@wordpress/scripts-10.0.0 chore(package): update @wordpress/scripts to version 10.0.0 * chore: update `stylelint-scss` to 3.17.2 * feat: prepare `17.0.0` release * refactor: rename `stylelint-config-wordpress` to `stylelint-config` * refactor: rename `stylelint-config-wordpress` to `@wordpress/stylelint-config` in `package.json` * refactor: remove `@commitlint` from `@wordpress/stylelint-config` * refactor: remove `husky` from `@wordpress/stylelint-config` * refactor: trim npm package keywords from `@wordpress/stylelint-config` * refactor: remove `.editorconfig` from `@wordpress/stylelint-config` * refactor: remove `npmpub` from `@wordpress/stylelint-config` * refactor: remove `eslintConfig` from `@wordpress/stylelint-config` * refactor: remove `remarkConfig` from `@wordpress/stylelint-config` * refactor: remove `remark` from `@wordpress/stylelint-config` * refactor: remove `engines` from `@wordpress/stylelint-config` * refactor: remove `prettier.config.js` from `@wordpress/stylelint-config` * refactor: remove `.gitattributes` from `@wordpress/stylelint-config` * refactor: remove `.gitignore` from `@wordpress/stylelint-config` * refactor: remove `.travis.yml` from `@wordpress/stylelint-config` * tests: refactor tests in `@wordpress/stylelint-config` * chore: add `.stylelintignore` for _invalid_ scss test fixtures in `@wordpress/stylelint-config` * Revert "chore: add `.stylelintignore` for _invalid_ scss test fixtures in `@wordpress/stylelint-config`" This reverts commit 05ab441. * chore: add `.stylelintrc.json` for test fixtures in `@wordpress/stylelint-config` * tests: update Jest snapshots in `@wordpress/stylelint-config` * docs: update `docs/manifest.json` for `@wordpress/stylelint-config` * chore: update `@wordpress/stylelint-config` package description * chore: remove `devDependencies` from `@wordpress/stylelint-config` * chore: remove package `scripts` from `@wordpress/stylelint-config` * chore: remove superfluous `.stylelintignore` from `@wordpress/stylelint-config` * chore: add Lerna `publishConfig` to `@wordpress/stylelint-config` * Update Jest snapshots * Backfill release dates in changelog * Update package author * Update readme * Update comment to use renamed package name * Rename tests to match other packages * Remove stylelint `^10.1.0`, `^11.0.0`, and `^12.0.0` as peer dependency. Co-authored-by: greenkeeper[bot] <greenkeeper[bot]@users.noreply.github.com> Co-authored-by: Harley Oliver <harleyoliver@users.noreply.github.com> Co-authored-by: Heather B <heatherbrokmeier@gmail.com> Co-authored-by: Gary Jones <gary@gamajo.com> Co-authored-by: greenkeeper[bot] <23040076+greenkeeper[bot]@users.noreply.github.com> Co-authored-by: Dominik Schilling <dominikschilling+git@gmail.com>
This can serve as a discussion for creating an API for the editor. Share your thoughts 😄
The text was updated successfully, but these errors were encountered: