Source code missing
-
I like to inspect the source code that you used to build the index.js that is just a 200kb file of compiled and compressed JS code.
And btw, you are actually required to put the source into the plugin for on wordpress.org.
Is this on Github?
-
Hi @nico23!
Thanks for reaching out, as far as I know since the switch to Gutenberg including the uncompiled source code isn’t required.
I don’t have much in the index.js file as I’m mostly autoloading a bunch of things. here’s the index.js source code:
/**
* External Dependencies
*/
/**
* WordPress Dependencies
// */
import { registerBlockType } from '@wordpress/blocks';
import { registerFormatType } from '@wordpress/rich-text';
import { registerPlugin } from '@wordpress/plugins';
import { select, register, useSelect } from '@wordpress/data';
import { addFilter } from '@wordpress/hooks';
/**
* Internal Dependencies
*/
import './style.scss';
import './index.scss';
import * as darkModeToggle from './blocks/dark-mode-toggle';
const blocks = [
darkModeToggle,
];
blocks.forEach( ( { name, settings } ) => { registerBlockType( name, settings ); } );
import * as addUtilityClassesToBlocks from './filters/add-utility-classes-to-blocks';
import * as addDarkModeClassToEditor from './filters/add-dark-mode-class-to-editor';
import * as groupLink from './filters/group-link';
import * as queryTitleFilter from './filters/query-title-filter';
const filters = [
addUtilityClassesToBlocks,
addDarkModeClassToEditor,
groupLink,
queryTitleFilter,
];
filters.forEach( ( { name, filters } ) => {
filters.forEach(
( { hookName, namespace, callback } ) => { addFilter( hookName, namespace, callback ); }
);
} );
import * as inlineClasses from './formats/inline-classes';
registerFormatType( inlineClasses.name, inlineClasses.settings );
import * as pluginSettings from './plugins/plugin-settings';
const plugins = [
pluginSettings,
];
plugins.forEach( ( { name, settings } ) => { registerPlugin( name, settings ); } );
import * as pluginSettingsStore from './stores/plugin-settings';
register( pluginSettingsStore.store );Can you point out where this is written that the source is not required anymore?
I am interested in how you build the entire Gutenberg sidebar, specifically the class selector, what you just pasted is not really helping.4. Code must be (mostly) human readable.
Obscuring code by hiding it with techniques or systems similar to
p,a,c,k,e,r‘s obfuscate feature, uglify’s mangle, or unclear naming conventions such as$z12sdf813d, is not permitted in the directory. Making code non-human readable forces future developers to face an unnecessary hurdle, as well as being a common vector for hidden, malicious code.We require developers to provide public, maintained access to their source code and any build tools in one of the following ways:
- Include the source code in the deployed plugin
- A link in the readme to the development location
We strongly recommend you document how any development tools are to be used.
—-
The above is from the plugin guidelines, AFAIK they have not changed, for block only plugins there are additional guidelines come on top of the general plugin guidelines.
Got it, you’re wanting to bake the sidebar into your plugin? Here’s how that’s done:
/**
* External Dependencies
*/
/**
* WordPress Dependencies
*/
import { __ } from '@wordpress/i18n';
import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/editor';
/**
* Internal Dependencies
*/
import WelcomeGuide from '../../components/welcome-guide';
import pluginIcons from '../../utils/icons';
import Settings from '../../components/settings';
import './index.scss';
const slug = 'draft';
const Plugin = ( props ) => {
if ( !! wp.data.select('core/editor').getCurrentPostType() ) {
return (
<>
<PluginSidebarMoreMenuItem target={settings}>
{ __( 'Draft settings', 'draft' ) }
</PluginSidebarMoreMenuItem>
<WelcomeGuide />
<PluginSidebar
title={ __(Draft settings, 'draft' ) }
name={settings}
isPinnable={ false }
>
<Settings />
</PluginSidebar>
</>
);
}
return (
<>
<PluginSidebarMoreMenuItem target={settings}>
{ __( 'Draft settings', 'draft' ) }
</PluginSidebarMoreMenuItem>
<PluginSidebar
title={ __(Draft settings, 'draft' ) }
name={settings}
isPinnable={ false }
>
<Settings />
</PluginSidebar>
</>
);
};
const name =${ slug };
const settings = {
icon: pluginIcons.plugin,
render: Plugin,
};
export { name, settings };I think the key part of the plugin guidelines is this:
We strongly recommend you document how any development tools are to be used.Otherwise, the source code isn’t obscured in anyway, it’s compiled for production.
“obfuscate feature, uglify’s mangle” compiling is THAT it’s making it unreadable for humans! THAT IS “Making code non-human readable” or “obfuscate”
Why are you resisting putting the source into the plugin as required? I also again fail to see how your other copy&paste shows the code that builds the class selector. You again post code I did not ask for.
Just put the source into the plugin that you use to build the plugin, as required.-
This reply was modified 1 month, 3 weeks ago by
Nico.
Sorry @nico23 I’m not fully understanding the code you wanted and you mentioned being interested in including the entire Gutenberg sidebar. Here’s the code for the class selector:
/**
* External Dependencies
*/
/**
* WordPress Dependencies
*/
import { __ } from '@wordpress/i18n';
import { createHigherOrderComponent } from '@wordpress/compose';
import { BlockControls, InspectorAdvancedControls } from '@wordpress/block-editor';
import { BaseControl, Button, MenuGroup, ToolbarDropdownMenu, TextControl } from "@wordpress/components";
import { dispatch, useSelect } from '@wordpress/data';
import { getPath } from '@wordpress/url';
const { openGeneralSidebar } = dispatch( 'core/edit-post' ) || {};
const { openGeneralSidebar: openGeneralSidebarSiteEditor } = dispatch( 'core/edit-site' ) || {};
/**
* Internal Dependencies
*/
import ClassPicker from '../../components/class-picker';
import pluginIcons from '../../utils/icons';
import './index.scss';
const slug = 'draft';
const addUtilityClassesToBlockEdit = createHigherOrderComponent(
( BlockEdit ) => {
return ( props ) => {
const {
setAttributes,
isSelected,
} = props;
let {
attributes: {
className,
},
} = props;
const isSiteEditor = getPath( window.location.href )?.includes(
'site-editor.php'
);
const { pluginSettings, isSavingPost, isAutosavingPost } = useSelect(
( select ) => {
const pluginSettings = select(
${ slug }/settings
).getPluginSettings();
// const isSavingPost = select('core/editor').isSavingPost();
// const isAutosavingPost = select('core/editor').isAutosavingPost();
return {
pluginSettings,
// isAutosavingPost,
// isSavingPost,
};
} );
const { mode } = pluginSettings;
const onChange = ( newValues, { action, removedValue } ) => {
if( !! newValues ) {
className = newValues
.map( ( newValue ) => {
let { value } = newValue;
return value;
} )
.toString()
.replace( /,/g, ' ' );
}
if( ! newValues ) {
className = '';
}
setAttributes( {
className,
} );
};
if( !! className ) {
className = className.split( ' ' );
className = className.map( ( option ) => {
return {
label: option.replace( 'tw-', '' ),
value: option,
};
} )
}
return (
<>
<BlockEdit
{ ...props }
/>
{
mode === 'development' &&
<>
<BlockControls
group="other"
>
<ToolbarDropdownMenu
icon={ pluginIcons.plugin }
label={ __( 'Add Utility Classes', 'draft' ) }
popoverProps={ {
position: 'bottom right',
variant: 'alternate',
} }
menuProps={ { 'className': 'no-icons' } }>
{ ( { onClose } ) => (
<>
<MenuGroup
className="pb-0"
>
<BaseControl
className="mt-0"
help={ __(Separate multiple classes with spaces., 'draft' ) }
>
<TextControl
label="Additional CSS Class(es)"
value={ !! className ? className.map( className => className.value ).toString().replace(/,/g,' ') : '' }
onChange={ ( nextValue ) => {
setAttributes( {
className:
nextValue !== ''
? nextValue
: undefined,
} )
} }
/>
</BaseControl>
<ClassPicker
onChange={ onChange }
className={ className }
autofocus={ false }
blurInputOnSelect={ false }
/>
</MenuGroup>
<MenuGroup>
<Button variant="link" onClick={ () => isSiteEditor ? openGeneralSidebarSiteEditor(${ slug }/settings) : openGeneralSidebar(${ slug }/settings) }>{ __( 'Edit default settings', 'draft' ) }</Button>
</MenuGroup>
</>
) }
</ToolbarDropdownMenu>
</BlockControls>
<InspectorAdvancedControls>
<ClassPicker
onChange={ onChange }
className={ className }
autofocus={ false }
blurInputOnSelect={ false }
/>
<Button variant="link" onClick={ () => isSiteEditor ? openGeneralSidebarSiteEditor(${ slug }/settings) : openGeneralSidebar(${ slug }/settings) }>{ __( 'Edit default settings', 'draft' ) }</Button>
</InspectorAdvancedControls>
</>
}
</>
);
}
},
'addUtilityClassesToBlockEdit'
);
const name = 'add-utility-classes-to-blocks';
const filters = [
{
hookName: 'editor.BlockEdit',
namespace:${ slug }/add-draft-classes-to-block-edit,
callback: addUtilityClassesToBlockEdit,
},
];
export { name, filters };I think the key part you’re looking for is using the InspectorAdvancedControls component:
import { BlockControls, InspectorAdvancedControls } from '@wordpress/block-editor';And then you just drop children in there:
<InspectorAdvancedControls>
<ClassPicker
onChange={ onChange }
className={ className }
autofocus={ false }
blurInputOnSelect={ false }
/>
<Button variant="link" onClick={ () => isSiteEditor ? openGeneralSidebarSiteEditor(${ slug }/settings) : openGeneralSidebar(${ slug }/settings) }>{ __( 'Edit default settings', 'draft' ) }</Button>
</InspectorAdvancedControls>I’m sharing code snippets to try and help you find what you’re looking for. It’s not resistance so much as the plugin is free, there aren’t many new users using the plugin, few free plugin customers convert to paid plugin customers, and I’m a one person operation. 🥴
Hopefully this gives you the information you need.
I indeed consider what you are going resisting. I asked for the class selector the first time. I totally fail to get why this takes endless attempts to give me what I asked for. What about “class selector” was so hard to understand?
Also, you cherry-picked some text about optional tool chain description from the guidelines and ignored the rest. Ignoring the fact about human-readable … I wrote an email to the plugin team asking for clarification on the guidelines. The way I understand it, you must put the uncompressed readable actual sources into the plugin or link to the sources somewhere else!
Leaving aside what is required or not, you seem to be willing to share but in the most annoying way possible, with little snippets that I need to copy and paste now and try to build together that reference files I do not have …import ClassPicker from '../../components/class-picker';This is a component you wrote? You still have failed to share the damn code to actually build it, this is crazy. It seems similar to the WordPress tag selector, but you need comma or enter to separate tags and this operates by spaces, it pulls in a list of classes for quick selection list. I still do not have the code for it, just weird what you are doing. Like, what is keeping you from putting the source out?
And you do not need to tell me about your one-man operation, I am a one-man operation myself, I maintain my own plugin here for 13 years! And I have the sources in my plugin and on Github. It’s not hard. If you can copy and paste them here you can dump them somewhere, I really do not get you.
Instead of putting the sources out in some way, you prematurely marked this as “solved” and dumped some meaningless BS with “there is hardly anything in there”. Yeah, only 16k lines prettified unreadable code, considering that wp-scripts that you seem to be using does actually not compile WP internal deps into the file that is quite a lot … but you were eager to jump on the fact that you do not have to share you build process … seems to be wp-scripts, you act just weird.-
This reply was modified 1 month, 3 weeks ago by
Nico.
Answer from the plugins team (Of course I was right):
Short answer: yes – The Plugin Directory requires code to be (mostly) human readable. If you ship compiled/minified JavaScript you must also make the human‑readable source available (either include it in the plugin package or provide a clear link in the readme to a public repository and build instructions).
Clarification on minification vs mangling/obfuscation:
- Minification (removing whitespace, comments, shortening non-symbol names where readable) is acceptable for delivery, but it must not prevent humans from reasonably understanding or auditing the code.
- Uglify’s mangle option renames identifiers (variables/functions) to very short names (a, b, c, …). Combined with other transformations this often amounts to obfuscation — making the code effectively unreadable. That kind of mangling/obfuscation is disallowed under guideline #4.
Thanks,
WordPress Plugins Team—–
Yesterday you answered, marked it as resolved within minutes, took like three attempts to give me the code over a time of like 3 hours or something like that.
You could dump the code on Github/Gitlab/Codeberg/whatever. You could have quickly zipped up the plugins and send it. I still not have what I asked for. I also think it’s a security concern to have 200k unreadable code that takes ages to decipher without the source to it.
Now comply with the guidelines! Here I thought I can learn from your code, I could possibly be done with it. If I invested the time trying to figure this out on my own or with the help of AI. But this is about principle now.
You must be logged in to reply to this topic.