Skip to content

4 features to review in this PR #213

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 7 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/css/edit.scss
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,9 @@ p.snippet-scope, .snippet-scope p {
.wrap .notice {
scroll-margin: 0.75em;
}

#edit-snippet-form-container .cs-sticky-notice {
position: sticky;
top: 40px;
z-index: 100;
}
14 changes: 6 additions & 8 deletions src/css/manage.scss
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ $inactive-color: #ccc;
height: 17px;
border-radius: 34px;
background-color: #ccc;
box-shadow: 0 0px 1px 0px rgba(0, 0, 0, .2);
transition: all 200ms ease-in-out !important;

&:hover {
box-shadow: 0 1px 3px 0px rgba(0, 0, 0, 0.5);
}

&::before {
transition: all .4s;
Expand All @@ -72,20 +78,12 @@ $inactive-color: #ccc;
border-radius: 50%;
}

&:hover::before {
transform: translateX(40%);
}

.snippets .active-snippet & {
background-color: $active-color;

&::before {
transform: translateX(100%);
}

&:hover::before {
transform: translateX(60%);
}
}

.snippets .erroneous-snippet &::before {
Expand Down
2 changes: 2 additions & 0 deletions src/js/components/SnippetForm/fields/ScopeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { buildShortcodeTag } from '../../../utils/shortcodes'
import { getSnippetType } from '../../../utils/snippets'
import { CopyToClipboardButton } from '../../common/CopyToClipboardButton'
import { useSnippetForm } from '../../../hooks/useSnippetForm'
import { truncateWords } from '../../../utils/text'
import type { ShortcodeAtts } from '../../../utils/shortcodes'
import type { SnippetScope } from '../../../types/Snippet'
import type { Dispatch, SetStateAction} from 'react'
Expand Down Expand Up @@ -117,6 +118,7 @@ const ShortcodeInfo: React.FC = () => {
<>
<ShortcodeTag atts={{
id: snippet.id,
name: truncateWords(snippet.name),
network: snippet.network ?? isNetworkAdmin(),
...options
}} />
Expand Down
17 changes: 12 additions & 5 deletions src/js/components/SnippetForm/page/Notices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,23 @@ interface DismissibleNoticeProps {
classNames?: classnames.Argument
onRemove: MouseEventHandler<HTMLButtonElement>
children?: ReactNode
autoHide?: boolean
}

const DismissibleNotice: React.FC<DismissibleNoticeProps> = ({ classNames, onRemove, children }) => {
const DismissibleNotice: React.FC<DismissibleNoticeProps> = ({ classNames, onRemove, children, autoHide = true }) => {
useEffect(() => {
if (window.CODE_SNIPPETS_EDIT?.scrollToNotices) {
window.scrollTo({ top: 0, behavior: 'smooth' })
if (autoHide) {
const timer = setTimeout(() => {
onRemove({} as React.MouseEvent<HTMLButtonElement>)
}, 5000)

return () => clearTimeout(timer)
}
}, [])
return () => {} // eslint-disable-line
}, [autoHide, onRemove])

return (
<div id="message" className={classnames('notice fade is-dismissible', classNames)}>
<div id="message" className={classnames('cs-sticky-notice notice fade is-dismissible', classNames)}>
<>{children}</>

<button type="button" className="notice-dismiss" onClick={event => {
Expand All @@ -45,6 +51,7 @@ export const Notices: React.FC = () => {
<DismissibleNotice
classNames="error"
onRemove={() => setSnippet(previous => ({ ...previous, code_error: null }))}
autoHide={false}
>
<p>
<strong>{sprintf(
Expand Down
1 change: 1 addition & 0 deletions src/js/types/Shortcodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface SourceShortcodeAtts {

export interface ContentShortcodeAtts {
id: string
name: string
php: boolean
format: boolean
shortcodes: boolean
Expand Down
7 changes: 7 additions & 0 deletions src/js/utils/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ export const trimLeadingChar = (text: string, character: string): string =>

export const trimTrailingChar = (text: string, character: string): string =>
character === text.charAt(text.length - 1) ? text.slice(0, -1) : text

export const truncateWords = (text: string, wordCount: number = 3): string => {
const words = text.trim().split(/\s+/);
return words.length > wordCount
? `${words.slice(0, wordCount).join(' ')}...`
: text;
};
28 changes: 25 additions & 3 deletions src/php/front-end/class-front-end.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ class Front_End {
*/
const PRISM_HANDLE = 'code-snippets-prism';

/**
* Maximum depth for shortcode recursion.
*/
const MAX_SHORTCODE_DEPTH = 5;

/**
* Class constructor
*/
Expand Down Expand Up @@ -235,7 +240,7 @@ protected function convert_boolean_attribute_flags( array $atts, array $boolean_
*
* @return string Evaluated shortcode content.
*/
protected function evaluate_shortcode_content( Snippet $snippet, array $atts ): string {
protected function evaluate_shortcode_content( Snippet $snippet, array $atts ): string {
if ( empty( $atts['php'] ) ) {
return $snippet->code;
}
Expand Down Expand Up @@ -325,8 +330,25 @@ public function render_content_shortcode( array $atts ): string {
// Remove this shortcode from the list to prevent recursion.
remove_shortcode( self::CONTENT_SHORTCODE );

// Evaluate shortcodes.
$content = do_shortcode( $atts['format'] ? shortcode_unautop( $content ) : $content );
// Recursion depth is limited to prevent infinite loops.
static $depth = 0;
$max_depth = self::MAX_SHORTCODE_DEPTH;

// Find the shortcode in the content and replace it with the evaluated content.
$content = preg_replace_callback(
'/\[' . self::CONTENT_SHORTCODE . '([^\]]*)\]/',
function ($matches) use (&$depth, $max_depth) {
if ($depth >= $max_depth) {
return '<!-- Max shortcode depth reached -->';
}
$depth++;
$atts = shortcode_parse_atts($matches[1]);
$result = $this->render_content_shortcode($atts);
$depth--;
return $result;
},
$content
);

// Add this shortcode back to the list.
add_shortcode( self::CONTENT_SHORTCODE, [ $this, 'render_content_shortcode' ] );
Expand Down
Loading