Make WordPress Core

Ticket #41689: 41689.2.diff

File 41689.2.diff, 131.1 KB (added by kraftbj, 7 years ago)

2nd pass

  • src/wp-admin/admin-ajax.php

    diff --git src/wp-admin/admin-ajax.php src/wp-admin/admin-ajax.php
    index f5b1c50f9a..66e543cded 100644
    $core_actions_post = array( 
    6161        'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor',
    6262        'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'get-revision-diffs',
    6363        'save-user-color-scheme', 'update-widget', 'query-themes', 'parse-embed', 'set-attachment-thumbnail',
    64         'parse-media-shortcode', 'destroy-sessions', 'install-plugin', 'update-plugin', 'press-this-save-post',
    65         'press-this-add-category', 'crop-image', 'generate-password', 'save-wporg-username', 'delete-plugin',
    66         'search-plugins', 'search-install-plugins', 'activate-plugin', 'update-theme', 'delete-theme',
    67         'install-theme', 'get-post-thumbnail-html', 'get-community-events',
     64        'parse-media-shortcode', 'destroy-sessions', 'install-plugin', 'update-plugin', 'crop-image',
     65  'generate-password', 'save-wporg-username', 'delete-plugin', 'search-plugins',
     66  'search-install-plugins', 'activate-plugin', 'update-theme', 'delete-theme', 'install-theme',
     67  'get-post-thumbnail-html', 'get-community-events',
    6868);
    6969
    7070// Deprecated
    71 $core_actions_post[] = 'wp-fullscreen-save-post';
     71$core_actions_post_deprecated = array( 'wp-fullscreen-save-post', 'press-this-save-post', 'press-this-add-category' );
     72$core_actions_post = array_merge( $core_actions_post, $core_actions_post_deprecated );
    7273
    7374// Register core Ajax calls.
    7475if ( ! empty( $_GET['action'] ) && in_array( $_GET['action'], $core_actions_get ) )
  • deleted file src/wp-admin/css/press-this-editor.css

    diff --git src/wp-admin/css/press-this-editor.css src/wp-admin/css/press-this-editor.css
    deleted file mode 100644
    index 8e10d86d55..0000000000
    + -  
    1 /*
    2 Press This TinyMCE editor styles :)
    3 */
    4 
    5 
    6 /**
    7 * Links
    8 */
    9 a {
    10         color: #0073aa;
    11 }
    12 
    13 a:visited {
    14         color: #0073aa;
    15 }
    16 
    17 a:hover,
    18 a:focus,
    19 a:active {
    20         color: #00a0d2;
    21 }
    22 
    23 
    24 /**
    25 * Lists
    26 */
    27 ul,
    28 ol {
    29         margin: 0 0 1.5em 3em;
    30 }
    31 
    32 ul {
    33         list-style: disc;
    34 }
    35 
    36 ol {
    37         list-style: decimal;
    38 }
    39 
    40 li > ul,
    41 li > ol {
    42         margin-bottom: 0;
    43         margin-left: 1.5em;
    44 }
    45 
    46 dt {
    47         font-weight: 700;
    48 }
    49 
    50 dd {
    51         margin: 0 1.5em 1.5em;
    52 }
    53 
    54 
    55 /**
    56 * Media
    57 *
    58 * Basic image and object styles
    59 */
    60 img {
    61         max-width: 100%;
    62         height: auto;
    63 }
    64 
    65 /* Makes sure embeds and iframes fit inside their containers */
    66 embed,
    67 iframe,
    68 object {
    69         max-width: 100%;
    70 }
    71 
    72 
    73 /**
    74 * TinyMCE styles
    75 *
    76 * Pretty dang good.
    77 */
    78 body {
    79         color: #404040;
    80         font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
    81         font-size: 20px;
    82         font-weight: 400;
    83         line-height: 1.6;
    84 }
    85 @media (max-width: 900px) {
    86         body#tinymce {
    87                 padding-top: 30px !important;
    88         }
    89 }
    90 @media (max-width: 640px) {
    91         body {
    92                 font-size: 16px;
    93         }
    94 }
    95 @media (max-width: 320px) {
    96         body {
    97                 margin: 0 15px;
    98         }
    99 }
    100 
    101 #tinymce b,
    102 #tinymce strong {
    103         /* overrides TinyMCE's !important. Woohoo. */
    104         font-weight: 700 !important;
    105 }
    106 
    107 blockquote {
    108         margin: 1em 1.5em;
    109         color: #9ea7af;
    110         font-size: em(25px);
    111         font-style: italic;
    112 }
    113 @media (max-width: 900px) {
    114         blockquote {
    115                 margin: 1.5em 1em;
    116         }
    117 }
    118 
    119 ul,
    120 ol {
    121         margin: 0 0 1.5em .75em;
    122 }
  • deleted file src/wp-admin/css/press-this.css

    diff --git src/wp-admin/css/press-this.css src/wp-admin/css/press-this.css
    deleted file mode 100644
    index bafea24d14..0000000000
    + -  
    1 /*
    2 Press This styles :)
    3 */
    4 
    5 
    6 /**
    7 * Normalize
    8 *
    9 * normalize.css v3.0.0 | MIT License | git.io/normalize
    10 */
    11 html {
    12         font-family: sans-serif;
    13         -ms-text-size-adjust: 100%;
    14         -webkit-text-size-adjust: 100%;
    15 }
    16 
    17 body {
    18         margin: 0;
    19 }
    20 
    21 *,
    22 *:before,
    23 *:after {
    24         box-sizing: border-box;
    25 }
    26 @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
    27         *,
    28         *:before,
    29         *:after {
    30                 -webkit-font-smoothing: antialiased;
    31         }
    32 }
    33 
    34 article,
    35 aside,
    36 details,
    37 figcaption,
    38 figure,
    39 footer,
    40 header,
    41 hgroup,
    42 main,
    43 nav,
    44 section,
    45 summary {
    46         display: block;
    47 }
    48 
    49 audio,
    50 canvas,
    51 progress,
    52 video {
    53         display: inline-block;
    54         vertical-align: baseline;
    55 }
    56 
    57 audio:not([controls]) {
    58         display: none;
    59         height: 0;
    60 }
    61 
    62 [hidden],
    63 template {
    64         display: none;
    65 }
    66 
    67 a {
    68         background: transparent;
    69 }
    70 
    71 a:active,
    72 a:hover {
    73         outline: 0;
    74 }
    75 
    76 abbr[title] {
    77         border-bottom: 1px dotted;
    78 }
    79 
    80 b,
    81 strong {
    82         font-weight: 700;
    83 }
    84 
    85 dfn {
    86         font-style: italic;
    87 }
    88 
    89 h1 {
    90         font-size: 2em;
    91         margin: 0.67em 0;
    92 }
    93 
    94 mark {
    95         background: #ff0;
    96         color: #000;
    97 }
    98 
    99 small {
    100         font-size: 80%;
    101 }
    102 
    103 sub,
    104 sup {
    105         font-size: 75%;
    106         line-height: 0;
    107         position: relative;
    108         vertical-align: baseline;
    109 }
    110 
    111 sup {
    112         top: -0.5em;
    113 }
    114 
    115 sub {
    116         bottom: -0.25em;
    117 }
    118 
    119 img {
    120         border: 0;
    121 }
    122 
    123 svg:not(:root) {
    124         overflow: hidden;
    125 }
    126 
    127 figure {
    128         margin: 1em 40px;
    129 }
    130 
    131 hr {
    132         box-sizing: content-box;
    133         height: 0;
    134 }
    135 
    136 pre {
    137         overflow: auto;
    138 }
    139 
    140 code,
    141 kbd,
    142 pre,
    143 samp {
    144         font-family: monospace, monospace;
    145         font-size: 1em;
    146 }
    147 
    148 button,
    149 input,
    150 optgroup,
    151 select,
    152 textarea {
    153         color: inherit;
    154         font: inherit;
    155         margin: 0;
    156 }
    157 
    158 button {
    159         overflow: visible;
    160 }
    161 
    162 button,
    163 select {
    164         text-transform: none;
    165 }
    166 
    167 button,
    168 html input[type="button"],
    169 input[type="reset"],
    170 input[type="submit"] {
    171         -webkit-appearance: button;
    172         cursor: pointer;
    173 }
    174 
    175 button[disabled],
    176 html input[disabled] {
    177         cursor: default;
    178 }
    179 
    180 button::-moz-focus-inner,
    181 input::-moz-focus-inner {
    182         border: 0;
    183         padding: 0;
    184 }
    185 
    186 input {
    187         line-height: normal;
    188 }
    189 
    190 input[type="checkbox"],
    191 input[type="radio"] {
    192         box-sizing: border-box;
    193         padding: 0;
    194 }
    195 
    196 input[type="number"]::-webkit-inner-spin-button,
    197 input[type="number"]::-webkit-outer-spin-button {
    198         height: auto;
    199 }
    200 
    201 input[type="search"] {
    202         -webkit-appearance: textfield;
    203         box-sizing: content-box;
    204 }
    205 
    206 input[type="search"]::-webkit-search-cancel-button,
    207 input[type="search"]::-webkit-search-decoration {
    208         -webkit-appearance: none;
    209 }
    210 
    211 fieldset {
    212         border: 0;
    213         margin: 0;
    214         padding: 0;
    215 }
    216 
    217 legend {
    218         border: 0;
    219         padding: 0;
    220 }
    221 
    222 textarea {
    223         overflow: auto;
    224 }
    225 
    226 optgroup {
    227         font-weight: 700;
    228 }
    229 
    230 table {
    231         border-collapse: collapse;
    232         border-spacing: 0;
    233 }
    234 
    235 td,
    236 th {
    237         padding: 0;
    238 }
    239 
    240 ::-webkit-input-placeholder {
    241         color: #72777c;
    242 }
    243 
    244 ::-moz-placeholder {
    245    color: #72777c;
    246    opacity: 1;
    247 }
    248 
    249 :-ms-input-placeholder {
    250         color: #72777c;
    251 }
    252 
    253 .clearfix:before,
    254 .clearfix:after {
    255         content: "";
    256         display: table;
    257 }
    258 .clearfix:after {
    259         clear: both;
    260 }
    261 
    262 .hide-if-js {
    263         display: none;
    264 }
    265 
    266 .screen-reader-text {
    267         position: absolute;
    268         margin: -1px;
    269         padding: 0;
    270         height: 1px;
    271         width: 1px;
    272         overflow: hidden;
    273         clip: rect(0 0 0 0);
    274         border: 0;
    275 }
    276 
    277 
    278 /**
    279 * Typography
    280 *
    281 * Base element typographic styles.
    282 */
    283 body,
    284 button,
    285 input,
    286 select,
    287 textarea {
    288         color: #404040;
    289         font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
    290         font-size: 20px;
    291         font-weight: 400;
    292         line-height: 1.6;
    293 }
    294 
    295 h1,
    296 h2,
    297 h3,
    298 h4,
    299 h5,
    300 h6 {
    301         clear: both;
    302 }
    303 
    304 p {
    305         margin-bottom: 1.5em;
    306 }
    307 
    308 b,
    309 strong {
    310         font-weight: 700;
    311 }
    312 
    313 
    314 /**
    315 * Buttons
    316 *
    317 * Pushing buttons is what I do.
    318 */
    319 
    320 .scan-submit {
    321         display: inline-block;
    322         margin: 0;
    323         padding: 0 10px 1px;
    324         border-width: 1px;
    325         border-style: solid;
    326         border-radius: 3px;
    327         font-size: 13px;
    328         line-height: 2;
    329         text-decoration: none;
    330         white-space: nowrap;
    331         cursor: pointer;
    332         -webkit-appearance: none;
    333 }
    334 
    335 .split-button {
    336         position: relative;
    337         display: inline-block;
    338         vertical-align: middle;
    339 }
    340 
    341 .split-button-body {
    342         display: none;
    343         position: absolute;
    344         bottom: 39px;
    345         right: 0;
    346         border: 1px solid #ddd;
    347         background-color: #fff;
    348         min-width: 180px;
    349         max-width: 100%;
    350         margin: 0;
    351         padding: 8px;
    352         list-style: none;
    353         box-shadow: 1px 0 4px rgba( 0, 0, 0, 0.15 );
    354 }
    355 
    356 .split-button-body:before,
    357 .split-button-body:after {
    358         position: absolute;
    359         right: 12px;
    360         display: block;
    361         width: 0;
    362         height: 0;
    363         border-style: solid;
    364         border-color: transparent;
    365         content: "";
    366 }
    367 
    368 .split-button-body:before {
    369         bottom: -18px;
    370         border-top-color: #ccc;
    371         border-width: 9px;
    372         right: 11px;
    373 }
    374 
    375 .split-button-body:after {
    376         bottom: -16px;
    377         border-top-color: #fff;
    378         border-width: 8px;
    379 }
    380 
    381 .split-button-body .split-button-option {
    382         display: block;
    383         padding: 5px 15px;
    384         margin: 0;
    385         width: 100%;
    386         border: 0;
    387         text-align: left;
    388         line-height: 2;
    389         background: none;
    390         color: inherit;
    391         text-decoration: none;
    392         outline: none;
    393         transition: none;
    394 }
    395 
    396 .split-button-body .split-button-option:hover,
    397 .split-button-body .split-button-option:active {
    398         color: inherit;
    399 }
    400 
    401 .is-open .split-button-body {
    402         display: block;
    403 }
    404 
    405 .split-button-primary,
    406 .split-button-toggle {
    407         border-radius: 0;
    408         display: block;
    409         margin: 0;
    410         font-size: 13px;
    411         text-decoration: none;
    412         white-space: nowrap;
    413         cursor: pointer;
    414         -webkit-appearance: none;
    415         line-height: 2;
    416         padding: 0 10px 1px;
    417         background: #0085ba;
    418         border-color: #0073aa #006799 #006799;
    419         border-width: 1px;
    420         border-style: solid;
    421  box-shadow: 0 1px 0 #006799;
    422         color: #fff;
    423         text-shadow: 0 -1px 1px #006799,
    424                 1px 0 1px #006799,
    425                 0 1px 1px #006799,
    426                 -1px 0 1px #006799;
    427 }
    428 
    429 .split-button-primary {
    430         border-top-left-radius: 3px;
    431         border-bottom-left-radius: 3px;
    432         border-right: 0 none;
    433         float: left;
    434 }
    435 
    436 .split-button-toggle {
    437         padding: 0;
    438         border-top-right-radius: 3px;
    439         border-bottom-right-radius: 3px;
    440         border-left: 1px solid #006799;
    441         float: right;
    442 }
    443 
    444 .split-button-toggle i {
    445         margin: 4px 20px 3px 0;
    446         padding: 0 10px;
    447 }
    448 
    449 .split-button-primary:hover,
    450 .split-button-toggle:hover {
    451         outline: none;
    452         background: #008ec2;
    453         border-color: #006799;
    454 }
    455 
    456 .split-button-primary:focus,
    457 .split-button-toggle:focus {
    458         outline: none;
    459         box-shadow: 0 1px 0 #0073aa,
    460                 0 0 2px 1px #33b3db;
    461 }
    462 
    463 .split-button-primary:active,
    464 .split-button-toggle:active {
    465         background: #0073aa;
    466         border-color: #006799;
    467  box-shadow: inset 0 2px 10px #006799, 0 1px 0 #0073aa;
    468 }
    469 
    470 /**
    471 * Forms
    472 *
    473 * So many input types.
    474 */
    475 button,
    476 input,
    477 select,
    478 textarea {
    479         font-size: 100%;
    480         margin: 0;
    481         vertical-align: baseline;
    482         *vertical-align: middle;
    483 }
    484 
    485 [type="checkbox"],
    486 [type="radio"] {
    487         padding: 0;
    488 }
    489 
    490 [type="search"] {
    491         -webkit-appearance: textfield;
    492         box-sizing: content-box;
    493 }
    494 
    495 [type="search"]::-webkit-search-decoration {
    496         -webkit-appearance: none;
    497 }
    498 
    499 button::-moz-focus-inner,
    500 input::-moz-focus-inner {
    501         border: 0;
    502         padding: 0;
    503 }
    504 
    505 [type="text"],
    506 [type="email"],
    507 [type="url"],
    508 [type="password"],
    509 [type="search"],
    510 textarea {
    511         padding: 0.4em 0.75em;
    512         color: #32373c;
    513         border: 1px solid #ccc;
    514 }
    515 
    516 [type="text"]:focus,
    517 [type="email"]:focus,
    518 [type="url"]:focus,
    519 [type="password"]:focus,
    520 [type="search"]:focus,
    521 textarea:focus {
    522         color: #32373c;
    523         outline: 0;
    524 }
    525 
    526 textarea {
    527         overflow: auto;
    528         padding-left: 3px;
    529         vertical-align: top;
    530 }
    531 
    532 
    533 /**
    534 * Links
    535 */
    536 a {
    537         color: #0073aa;
    538 }
    539 
    540 a:visited {
    541         color: #0073aa;
    542 }
    543 
    544 a:hover,
    545 a:focus,
    546 a:active {
    547         color: #00a0d2;
    548 }
    549 
    550 
    551 /**
    552 * Lists
    553 */
    554 ul,
    555 ol {
    556         margin: 0 0 1.5em 3em;
    557 }
    558 
    559 ul {
    560         list-style: disc;
    561 }
    562 
    563 ol {
    564         list-style: decimal;
    565 }
    566 
    567 li > ul,
    568 li > ol {
    569         margin-bottom: 0;
    570         margin-left: 1.5em;
    571 }
    572 
    573 dt {
    574         font-weight: 700;
    575 }
    576 
    577 dd {
    578         margin: 0 1.5em 1.5em;
    579 }
    580 
    581 
    582 /**
    583 * Post formats
    584 *
    585 * Complete styles for post formats UI
    586 */
    587 /* TODO if we remove the <br> during merge, this can go. */
    588 #post-formats-select br {
    589         display: none;
    590 }
    591 
    592 .post-format {
    593         width: 1px;
    594         height: 1px;
    595         position: absolute;
    596         top: -9999px;
    597 }
    598 
    599 .lt-ie9 .post-format {
    600         margin: 17px 12px 0 13px;
    601         width: auto;
    602         height: auto;
    603         position: static;
    604         top: auto;
    605         float: left;
    606         width: 16px;
    607         height: 16px;
    608 }
    609 
    610 .post-format-icon {
    611         position: relative;
    612         display: block;
    613         padding: 13px 2px 14px 13px;
    614         cursor: pointer;
    615 }
    616 
    617 .post-format-icon:before,
    618 .post-format-icon:after {
    619         content: "";
    620         display: inline-block;
    621         width: 20px;
    622         height: 20px;
    623         margin-right: 10px;
    624         font-size: 20px;
    625         line-height: 1;
    626         font-family: dashicons;
    627         text-decoration: inherit;
    628         color: #9ea7af;
    629         font-weight: 400;
    630         font-style: normal;
    631         vertical-align: top;
    632         text-align: center;
    633         transition: color .1s ease-in 0;
    634         -webkit-font-smoothing: antialiased;
    635         -moz-osx-font-smoothing: grayscale;
    636 }
    637 
    638 .post-format-icon:before {
    639         content: "\f109";
    640 }
    641 
    642 .post-format-icon:after {
    643         display: none;
    644         content: "\f147";
    645         float: right;
    646 }
    647 
    648 .post-format:checked + .post-format-icon {
    649         box-shadow: inset 6px 0 0 #00a0d2;
    650         background: rgba(46, 162, 204, 0.1);
    651 }
    652 
    653 .post-format:checked + .post-format-icon:before,
    654 .post-format:checked + .post-format-icon:after {
    655         color: #32373c;
    656 }
    657 
    658 .post-format:focus + .post-format-icon {
    659         background: #00a0d2;
    660         color: #fff;
    661 }
    662 
    663 .post-format:focus + .post-format-icon:before,
    664 .post-format:focus + .post-format-icon:after {
    665         color: #fff;
    666 }
    667 
    668 .post-format:checked + .post-format-icon:after {
    669         display: block;
    670 }
    671 
    672 .lt-ie9 .post-format-icon {
    673         margin-left: 16px;
    674 }
    675 
    676 .post-format-aside:before {
    677         content: "\f123";
    678 }
    679 
    680 .post-format-chat:before {
    681         content: "\f125";
    682 }
    683 
    684 .post-format-gallery:before {
    685         content: "\f161";
    686 }
    687 
    688 .post-format-link:before {
    689         content: "\f103";
    690 }
    691 
    692 .post-format-image:before {
    693         content: "\f128";
    694 }
    695 
    696 .post-format-quote:before {
    697         content: "\f122";
    698 }
    699 
    700 .post-format-status:before {
    701         content: "\f130";
    702 }
    703 
    704 .post-format-video:before {
    705         content: "\f126";
    706 }
    707 
    708 .post-format-audio:before {
    709         content: "\f127";
    710 }
    711 
    712 
    713 /**
    714 * Tags
    715 *
    716 * Complete styles for tags UI
    717 */
    718 .tagsdiv p {
    719         margin: 0;
    720 }
    721 
    722 .tagsdiv .ajaxtag {
    723         position: relative;
    724 }
    725 
    726 .tagsdiv .newtag {
    727         display: block;
    728         position: relative;
    729         padding: 11px 58px 11px 16px;
    730         width: 100%;
    731         border: 0;
    732         border-bottom: 1px solid #e5e5e5;
    733         font-size: 16px;
    734 }
    735 
    736 .tagsdiv .tagadd {
    737         position: absolute;
    738         top: 0;
    739         right: 0;
    740         bottom: 1px;
    741         border: 0;
    742         border-radius: 0;
    743         margin: 0;
    744         padding: 0 16px;
    745         background: #f7f7f7;
    746         border-left: 1px solid #f1f1f1;
    747         box-shadow: none;
    748 }
    749 
    750 .tagsdiv .tagadd:hover,
    751 .tagsdiv .tagadd:active,
    752 .tagsdiv .tagadd:focus {
    753         outline: 0;
    754         background: #2991b7;
    755         border-color: #20708e;
    756         color: #fff;
    757         box-shadow: none;
    758 }
    759 
    760 .tagsdiv .howto {
    761         color: #727272;
    762         font-style: italic;
    763         margin: 10px 0 6px 16px;
    764 }
    765 
    766 /* Tags */
    767 .tagchecklist {
    768         padding: 16px 28px 5px;
    769 }
    770 
    771 .tagchecklist:before,
    772 .tagchecklist:after {
    773         content: "";
    774         display: table;
    775 }
    776 
    777 .tagchecklist:after {
    778         clear: both;
    779 }
    780 
    781 .tagchecklist > span {
    782         float: left;
    783         margin-right: 25px;
    784         font-size: 13px;
    785         line-height: 1.8;
    786         white-space: nowrap;
    787         cursor: default;
    788 }
    789 
    790 @media (max-width: 600px) {
    791         .tagchecklist > span {
    792                 margin-bottom: 15px;
    793                 font-size: 16px;
    794                 line-height: 1.3;
    795         }
    796 }
    797 
    798 .tagchecklist .ntdelbutton {
    799         position: absolute;
    800         width: 24px;
    801         height: 24px;
    802         border: none;
    803         margin: 0 0 0 -19px;
    804         padding: 0;
    805         background: none;
    806         cursor: pointer;
    807         text-indent: 0;;
    808         position: absolute;
    809 }
    810 
    811 .tagchecklist .ntdelbutton .remove-tag-icon:before {
    812         content: "\f153";
    813         display: block;
    814         margin-left: 2px;
    815         height: 20px;
    816         width: 20px;
    817         border-radius: 50%;
    818         background: transparent;
    819         color: #0073aa;
    820         /* line-height tweak to vertically center the icon cross browsers */
    821         font: 400 16px/1.28 dashicons;
    822         text-align: center;
    823         -webkit-font-smoothing: antialiased;
    824 }
    825 
    826 .tagchecklist .ntdelbutton:focus {
    827         outline: 0;
    828 }
    829 
    830 .tagchecklist .ntdelbutton:hover .remove-tag-icon:before,
    831 .tagchecklist .ntdelbutton:focus .remove-tag-icon:before {
    832         color: #c00;
    833 }
    834 
    835 .tagchecklist .ntdelbutton:focus .remove-tag-icon:before {
    836         box-shadow:
    837                 0 0 0 1px #5b9dd9,
    838                 0 0 2px 1px rgba(30, 140, 190, .8);
    839 }
    840 
    841 /* THE TAG CLOUD. */
    842 .tagsdiv + p {
    843         margin: 0;
    844 }
    845 
    846 .press-this .tagcloud-link {
    847         display: block;
    848         margin: 0 16px 5px;
    849         padding: 0;
    850         text-decoration: none;
    851         outline: 0;
    852         color: inherit;
    853 }
    854 
    855 .press-this .tagcloud-link:hover,
    856 .press-this .tagcloud-link:active {
    857         color: inherit;
    858 }
    859 
    860 .tagcloud-link:focus {
    861         text-decoration: underline;
    862 }
    863 
    864 .popular-tags {
    865         border: none;
    866         line-height: 2em;
    867         padding: 8px 12px 12px;
    868         text-align: justify;
    869 }
    870 
    871 .popular-tags a {
    872         padding: 0 3px;
    873 }
    874 
    875 .the-tagcloud {
    876         margin: 0;
    877         padding: 16px;
    878 }
    879 
    880 .the-tagcloud a {
    881         text-decoration: none;
    882         outline: 0;
    883 }
    884 
    885 .the-tagcloud a:focus {
    886         text-decoration: underline;
    887 }
    888 
    889 .tagcloud h3 {
    890         margin: 2px 0 12px;
    891 }
    892 
    893 
    894 /**
    895 * Categories
    896 *
    897 * Complete styles for post categories UI
    898 */
    899 input[type="search"].categories-search,
    900 .add-category-name {
    901         display: block;
    902         width: 100%;
    903         padding: 0.85714em 1.07143em;
    904         border: 0;
    905         border-radius: 0;
    906         border-bottom: 1px solid #e5e5e5;
    907         font-size: 14px;
    908         -webkit-appearance: none;
    909         -moz-appearance: none;
    910         appearance: none;
    911 }
    912 
    913 @media (max-width: 600px) {
    914         input[type="search"].categories-search,
    915         .add-category-name {
    916                 /* Needs to be 16px to prevent zooming on iOS. Guh. */
    917                 font-size: 16px;
    918         }
    919 }
    920 
    921 .press-this .add-cat-toggle {
    922         float: right;
    923         margin-top: -45px;
    924         line-height: 20px;
    925         padding: 12px 10px 8px;
    926         color: #0073aa;
    927         text-decoration: none;
    928         transition: none;
    929 }
    930 
    931 .press-this .add-cat-toggle:focus {
    932         color: #00a0d2;
    933 }
    934 
    935 .press-this .add-cat-toggle.is-toggled {
    936         padding: 10px;
    937 }
    938 
    939 .press-this .add-cat-toggle.is-toggled .dashicons:before {
    940         content: "\f179";
    941 }
    942 
    943 .add-category {
    944         position: relative;
    945         border-bottom: 1px solid #e5e5e5;
    946 }
    947 
    948 .add-category.is-hidden {
    949         display: none;
    950 }
    951 
    952 .add-category .add-cat-submit {
    953         position: absolute;
    954         top: 0;
    955         right: 0;
    956         border: 0;
    957         border-radius: 0;
    958         padding: 12px 16px;
    959         background: #f7f7f7;
    960         border-left: 1px solid #f1f1f1;
    961 }
    962 
    963 .add-category .add-cat-submit:hover,
    964 .add-category .add-cat-submit:active,
    965 .add-category .add-cat-submit:focus {
    966         outline: 0;
    967         background: #2991b7;
    968         border-color: #20708e;
    969         color: #fff;
    970 }
    971 
    972 /* Parent category select */
    973 .postform-wrapper {
    974         padding: 12px;
    975 }
    976 
    977 .postform {
    978         display: block;
    979         margin: 0;
    980         width: 100%;
    981         height: 34px;
    982         border: 0;
    983         border-radius: 0;
    984         border: 1px solid #e5e5e5;
    985         background: #fff;
    986         background-size: 20px 20px;
    987         overflow: hidden;
    988         line-height: 21px;
    989         text-overflow: ellipsis;
    990         text-decoration: none;
    991         vertical-align: top;
    992         white-space: nowrap;
    993         cursor: pointer;
    994         outline: 0;
    995 }
    996 
    997 .postform:focus {
    998         border-color: #0073aa;
    999         box-shadow: 0 0 0 3px #00a0d2;
    1000         outline: 0;
    1001         -moz-outline: none;
    1002         -moz-user-focus: ignore;
    1003 }
    1004 
    1005 .postform::-ms-expand {
    1006         display: none;
    1007 }
    1008 
    1009 .postform::-ms-value {
    1010         background: none;
    1011         color: #727272;
    1012 }
    1013 
    1014 .postform:-moz-focusring {
    1015         color: transparent;
    1016         text-shadow: 0 0 0 #727272;
    1017 }
    1018 
    1019 /* Category list */
    1020 .categories-select {
    1021         margin: 0;
    1022         padding: 0;
    1023         list-style: none;
    1024 }
    1025 
    1026 .categories-select ul {
    1027         margin: 0;
    1028         padding: 0;
    1029         list-style: none;
    1030 }
    1031 
    1032 .category {
    1033         position: relative;
    1034         display: block;
    1035         padding: 13px 16px 14px 16px;
    1036         cursor: pointer;
    1037         background: #fff;
    1038 }
    1039 
    1040 .category:focus,
    1041 .category.selected:focus {
    1042         outline: 0;
    1043         background: #00a0d2;
    1044         color: #fff;
    1045 }
    1046 
    1047 .category.selected {
    1048         box-shadow: inset 6px 0 0 #00a0d2;
    1049         background: #E9F5F9;
    1050 }
    1051 
    1052 .category.selected:after {
    1053         display: inline-block;
    1054         content: "\f147";
    1055         position: absolute;
    1056         top: 13px;
    1057         right: 0;
    1058         width: 20px;
    1059         height: 20px;
    1060         margin-right: 10px;
    1061         font-size: 20px;
    1062         line-height: 1;
    1063         font-family: dashicons;
    1064         text-decoration: inherit;
    1065         color: #23282d;
    1066         font-weight: 400;
    1067         font-style: normal;
    1068         vertical-align: top;
    1069         text-align: center;
    1070         transition: color .1s ease-in 0;
    1071         -webkit-font-smoothing: antialiased;
    1072         -moz-osx-font-smoothing: grayscale;
    1073 }
    1074 
    1075 .category.selected:focus:after {
    1076         color: #fff;
    1077 }
    1078 
    1079 .categories-select ul .category {
    1080         padding-left: 24px;
    1081 }
    1082 
    1083 .categories-select ul ul .category {
    1084         padding-left: 32px;
    1085 }
    1086 
    1087 .categories-select ul ul ul .category {
    1088         padding-left: 40px;
    1089 }
    1090 
    1091 .categories-select ul ul ul ul .category {
    1092         padding-left: 48px;
    1093 }
    1094 
    1095 .categories-select ul ul ul ul ul .category {
    1096         padding-left: 56px;
    1097 }
    1098 
    1099 .categories-select ul ul ul ul ul ul .category {
    1100         padding-left: 64px;
    1101 }
    1102 
    1103 .categories-select .is-hidden {
    1104         display: none;
    1105 }
    1106 
    1107 .categories-select .is-hidden.searched-parent {
    1108         display: block;
    1109 }
    1110 
    1111 /* Category search */
    1112 .categories-search-wrapper {
    1113         position: relative;
    1114 }
    1115 
    1116 .categories-search-wrapper.is-hidden {
    1117         display: none;
    1118 }
    1119 
    1120 .categories-search-wrapper label {
    1121         position: absolute;
    1122         top: 50%;
    1123         right: 10px;
    1124         margin-top: -10px;
    1125         color: #9ea7af;
    1126 }
    1127 
    1128 
    1129 /**
    1130 * Main
    1131 */
    1132 html {
    1133         overflow: auto;
    1134 }
    1135 
    1136 body {
    1137         overflow-x: hidden;
    1138         height: 100%;
    1139 }
    1140 
    1141 html {
    1142         background: #fff;
    1143         box-shadow: -10px 0 0 rgba(0, 0, 0, 0.3);
    1144 }
    1145 
    1146 @media (max-width: 900px) {
    1147         body {
    1148                 font-size: 16px;
    1149         }
    1150 }
    1151 
    1152 @media (max-width: 320px) {
    1153         body {
    1154                 font-size: 14px;
    1155         }
    1156 }
    1157 
    1158 .lt-ie9 {
    1159         overflow: visible;
    1160 }
    1161 
    1162 .adminbar {
    1163         position: relative;
    1164         width: 100%;
    1165         padding: 0 0.8em;
    1166         min-height: 3.2em;
    1167         background: #23282d;
    1168         color: #fff;
    1169         z-index: 9999;
    1170 }
    1171 
    1172 .adminbar:before,
    1173 .adminbar:after {
    1174         content: "";
    1175         display: table;
    1176 }
    1177 
    1178 .adminbar:after {
    1179         clear: both;
    1180 }
    1181 
    1182 .adminbar .dashicons {
    1183         color: #a0a5aa; /* same as WP admin bar icons */
    1184 }
    1185 
    1186 .press-this .adminbar button {
    1187         position: absolute;
    1188         top: 50%;
    1189         right: 6px;
    1190         margin-top: -13px;
    1191         padding: 0 10px 1px;
    1192         font-size: 13px;
    1193         text-decoration: none;
    1194         transition: none;
    1195 }
    1196 
    1197 @media (max-width: 320px) {
    1198         .adminbar {
    1199                 min-height: 45px;
    1200         }
    1201 }
    1202 
    1203 .current-site {
    1204         margin-top: 0.5625em;
    1205         font-size: 16px;
    1206         line-height: 44px;
    1207         font-weight: 400;
    1208         overflow: hidden;
    1209         white-space: nowrap;
    1210         text-overflow: ellipsis;
    1211 }
    1212 
    1213 @media (max-width: 600px) {
    1214         .current-site {
    1215                 margin: 3px 0 0;
    1216         }
    1217 }
    1218 
    1219 @media (max-width: 320px) {
    1220         .current-site {
    1221                 margin: 0;
    1222                 font-size: 14px;
    1223         }
    1224 }
    1225 
    1226 .current-site-link {
    1227         text-decoration: none;
    1228 }
    1229 
    1230 .current-site-link:focus {
    1231         outline: 0;
    1232 }
    1233 
    1234 .current-site-link:focus .current-site-name{
    1235         text-decoration: underline;
    1236 }
    1237 
    1238 .current-site-name {
    1239         color: #ededed;
    1240 }
    1241 
    1242 @media (max-width: 320px) {
    1243         .current-site-name {
    1244                 font-weight: 600;
    1245         }
    1246 }
    1247 
    1248 .current-site .dashicons-wordpress {
    1249         position: relative;
    1250         top: -1px;
    1251         margin-right: 10px;
    1252         vertical-align: middle;
    1253 }
    1254 
    1255 .options,
    1256 .options.open .on-closed,
    1257 .options.closed .on-open {
    1258         display: none;
    1259 }
    1260 
    1261 @media (max-width: 900px) {
    1262         .options {
    1263                 display: block;
    1264         }
    1265 }
    1266 
    1267 .options-panel-back.is-hidden {
    1268         display: none;
    1269 }
    1270 
    1271 .options:focus .dashicons {
    1272         color: #fff;
    1273         text-decoration: none;
    1274 }
    1275 
    1276 .options .dashicons {
    1277         margin-top: 3px;
    1278 }
    1279 
    1280 .options {
    1281         color: #00a0d2;
    1282 }
    1283 
    1284 .alert {
    1285         position: relative;
    1286         margin: 0;
    1287         padding: 16px 50px;
    1288         border-bottom: 1px solid #e5e5e5;
    1289         font-size: 14px;
    1290 }
    1291 
    1292 .alert:before {
    1293         content: "";
    1294         position: absolute;
    1295         top: 50%;
    1296         left: 30px;
    1297         width: 8px;
    1298         height: 8px;
    1299         margin-top: -4px;
    1300         border-radius: 50%;
    1301         background: #00a0d2;
    1302 }
    1303 
    1304 @media (max-width: 600px) {
    1305         .alert {
    1306                 padding: 16px 35px;
    1307         }
    1308         .alert:before {
    1309                 left: 15px;
    1310         }
    1311 }
    1312 
    1313 .alert.is-error:before {
    1314         background: red;
    1315 }
    1316 
    1317 .scan {
    1318         position: relative;
    1319         border-bottom: 1px solid #e5e5e5;
    1320 }
    1321 
    1322 @media (max-width: 900px) {
    1323         .scan form {
    1324                 transition: opacity .3s ease-in-out;
    1325         }
    1326         .scan.is-hidden form {
    1327                 opacity: .2;
    1328                 pointer-events: none;
    1329         }
    1330 }
    1331 
    1332 .scan-url {
    1333         display: block;
    1334         border: 0;
    1335         padding: 0.85714em 1.07143em;
    1336         font-size: 14px;
    1337         width: 100%;
    1338 }
    1339 
    1340 @media (max-width: 600px) {
    1341         .scan-url {
    1342                 font-size: 16px;
    1343         }
    1344 }
    1345 
    1346 .scan-submit {
    1347         position: absolute;
    1348         top: 0;
    1349         right: 0;
    1350         bottom: 0;
    1351         padding: 0 1.07143em;
    1352         background: #f7f7f7;
    1353         border-color: #ddd;
    1354         border: 0;
    1355         border-left: 1px solid #f1f1f1;
    1356         border-radius: 0;
    1357         color: #555;
    1358         font-size: 14px;
    1359         line-height: 1.6;
    1360 }
    1361 
    1362 .scan-submit:hover,
    1363 .scan-submit:focus {
    1364         background: #008ec2;
    1365         border-color: #006799;
    1366         color: #fff;
    1367         outline: 0;
    1368 }
    1369 
    1370 .scan-submit:active {
    1371         background: #0073aa;
    1372         border-color: #006799;
    1373         color: #fff;
    1374 }
    1375 
    1376 .scan-submit:visited {
    1377         color: #555;
    1378 }
    1379 
    1380 .wrapper {
    1381         position: relative;
    1382         margin-bottom: 60px;
    1383         margin-right: 320px;
    1384 }
    1385 
    1386 .wrapper:before,
    1387 .wrapper:after {
    1388         content: "";
    1389         display: table;
    1390 }
    1391 
    1392 .wrapper:after {
    1393         clear: both;
    1394 }
    1395 
    1396 @media (max-width: 900px) {
    1397         .wrapper {
    1398                 margin: 0;
    1399                 width: 100%;
    1400         }
    1401 }
    1402 
    1403 .editor-wrapper {
    1404         overflow: auto;
    1405         float: left;
    1406         width: 100%;
    1407 }
    1408 
    1409 .editor-wrapper:before,
    1410 .editor-wrapper:after {
    1411         content: "";
    1412         display: table;
    1413 }
    1414 
    1415 .editor-wrapper:after {
    1416         clear: both;
    1417 }
    1418 
    1419 .editor {
    1420         padding: 0 1.5em 4.75em;
    1421         max-width: 700px;
    1422         margin: 0 auto;
    1423 }
    1424 
    1425 .spinner {
    1426         height: 20px;
    1427         width: 20px;
    1428         display: inline-block;
    1429         visibility: hidden;
    1430         background: url(../images/spinner.gif) no-repeat center;
    1431         background-size: 20px 20px;
    1432         opacity: 0.7;
    1433         filter: alpha(opacity=70);
    1434         line-height: 1;
    1435         vertical-align: middle;
    1436 }
    1437 
    1438 @media print,
    1439         (-webkit-min-device-pixel-ratio: 1.25),
    1440         (min-resolution: 120dpi) {
    1441 
    1442         .spinner {
    1443                 background-image: url(../images/spinner-2x.gif);
    1444         }
    1445 }
    1446 
    1447 .spinner.is-active {
    1448         visibility: visible;
    1449 }
    1450 
    1451 /* Make the text inside the editor textarea white. Prevents a "flash" on loading the page */
    1452 #pressthis {
    1453         color: #fff;
    1454 }
    1455 
    1456 @media (min-width: 901px) {
    1457         .editor {
    1458                 max-width: 760px;
    1459         }
    1460 }
    1461 
    1462 @media (max-width: 320px) {
    1463         .editor {
    1464                 padding: 0;
    1465         }
    1466 }
    1467 
    1468 .post-title,
    1469 .post-title-placeholder {
    1470         margin: 0;
    1471         padding: .83em 0;
    1472         width: 100%;
    1473         border-bottom: 1px solid #e5e5e5;
    1474         font-size: 32px;
    1475         line-height: 1.4;
    1476         font-weight: 700;
    1477 }
    1478 
    1479 .post-title:active,
    1480 .post-title:focus,
    1481 .post-title-placeholder:active,
    1482 .post-title-placeholder:focus {
    1483         outline: 0;
    1484         box-shadow: inset 0px -3px 0 #00a0d2;
    1485         border-color: #00a0d2;
    1486 }
    1487 
    1488 @media (max-width: 900px) {
    1489         .post-title,
    1490         .post-title-placeholder {
    1491                 font-size: 24px;
    1492         }
    1493 }
    1494 
    1495 @media (max-height: 400px) {
    1496         .post-title,
    1497         .post-title-placeholder {
    1498                 padding: 15px 0;
    1499                 font-size: 16px;
    1500         }
    1501 }
    1502 
    1503 @media (max-width: 320px) {
    1504         .post-title,
    1505         .post-title-placeholder {
    1506                 font-size: 16px;
    1507                 font-weight: 600;
    1508                 padding: 1.14286em 1.42857em;
    1509         }
    1510 }
    1511 
    1512 .post-title {
    1513         /* IE8 fallback */
    1514         background: url(data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///////wAAACH5BAEHAAIALAAAAAABAAEAAAICVAEAOw==);
    1515         background: none, none;
    1516 }
    1517 
    1518 .post-title:before {
    1519         /* Keeps empty container from collapsing */
    1520         content: "\a0";
    1521         display: inline-block;
    1522         width: 0;
    1523         speak: none;
    1524 }
    1525 
    1526 .post-title-placeholder {
    1527         position: absolute;
    1528         border: 0;
    1529         color: #82878c;
    1530         z-index: -1;
    1531 }
    1532 
    1533 .post-title-placeholder.is-hidden {
    1534         display: none;
    1535 }
    1536 
    1537 /* Suggested images */
    1538 .media-list-container {
    1539         position: relative;
    1540         padding: 2px 0;
    1541         border-bottom: 1px solid #e5e5e5;
    1542         display: none;
    1543 }
    1544 
    1545 .media-list-inner-container {
    1546         overflow: auto;
    1547         max-height: 150px;
    1548         max-height: 40vw;
    1549 }
    1550 
    1551 .media-list-container.has-media {
    1552         display: block;
    1553 }
    1554 
    1555 .media-list-inner-container:before,
    1556 .media-list-inner-container:after {
    1557         content: "";
    1558         display: table;
    1559 }
    1560 
    1561 .media-list-inner-container:after {
    1562         clear: both;
    1563 }
    1564 
    1565 .media-list {
    1566         margin: 0;
    1567         padding: 0;
    1568 }
    1569 
    1570 @media (min-width: 321px) {
    1571         .media-list-inner-container {
    1572                 max-height: 250px;
    1573                 max-height: 40vw;
    1574         }
    1575 }
    1576 
    1577 @media (min-width: 601px) {
    1578         .media-list-inner-container {
    1579                 max-height: 200px;
    1580                 max-height: 18.75vw;
    1581         }
    1582 }
    1583 
    1584 .wppt-all-media-list {
    1585         list-style: none;
    1586         margin: 0;
    1587         padding: 0;
    1588 }
    1589 
    1590 .suggested-media-thumbnail:focus,
    1591 .is-embed:focus {
    1592         outline: 0;
    1593         box-shadow: inset 0 0 0 3px #00a0d2;
    1594 }
    1595 
    1596 .suggested-media-thumbnail {
    1597         position: relative;
    1598         display: block;
    1599         float: left;
    1600         width: 16.66%;
    1601         padding: 16.66% 0 0 16.66%;
    1602         background-position: center;
    1603         background-repeat: no-repeat;
    1604         background-size: cover;
    1605         background-color: #d8d8d8;
    1606         color: #fff;
    1607         color: rgba(255, 255, 255, 0.6);
    1608         cursor: pointer;
    1609 }
    1610 
    1611 .suggested-media-thumbnail:hover,
    1612 .suggested-media-thumbnail:active,
    1613 .suggested-media-thumbnail:focus {
    1614         color: #fff;
    1615 }
    1616 
    1617 .suggested-media-thumbnail:before,
    1618 .suggested-media-thumbnail:after {
    1619         display: inline-block;
    1620         position: absolute;
    1621         font-size: 20px;
    1622         line-height: 1;
    1623         font-family: dashicons;
    1624         text-decoration: inherit;
    1625         font-weight: 400;
    1626         font-style: normal;
    1627         transition: color .1s ease-in 0;
    1628         -webkit-font-smoothing: antialiased;
    1629         -moz-osx-font-smoothing: grayscale;
    1630 }
    1631 
    1632 .suggested-media-thumbnail:before {
    1633         left: 50%;
    1634         top: 50%;
    1635         margin: -20px 0 0 -20px;
    1636         font-size: 40px;
    1637 }
    1638 
    1639 .suggested-media-thumbnail:after {
    1640         content: "\f132";
    1641         right: 3%;
    1642         bottom: 2%;
    1643 }
    1644 
    1645 @media (min-width: 601px) {
    1646         .suggested-media-thumbnail {
    1647                 width: 12.5%;
    1648                 padding: 12.5% 0 0 12.5%;
    1649         }
    1650 }
    1651 
    1652 .is-embed:before {
    1653         content: "\f104";
    1654         color: #fff;
    1655         color: rgba(255, 255, 255, 0.9);
    1656 }
    1657 
    1658 .is-embed.is-audio:hover:before,
    1659 .is-embed.is-audio:active:before,
    1660 .is-embed.is-audio:focus:before,
    1661 .is-embed.is-tweet:hover:before,
    1662 .is-embed.is-tweet:active:before,
    1663 .is-embed.is-tweet:focus:before {
    1664         color: #fff;
    1665 }
    1666 
    1667 .is-embed.is-video {
    1668         background-color: #23282d;
    1669 }
    1670 
    1671 .is-embed.is-video:hover:before,
    1672 .is-embed.is-video:active:before,
    1673 .is-embed.is-video:focus:before {
    1674         color: rgba(255, 255, 255, 0.2);
    1675 }
    1676 
    1677 .is-embed.is-video:before {
    1678         content: "\f236";
    1679 }
    1680 
    1681 .is-embed.is-audio {
    1682         background-color: #ff7d44;
    1683 }
    1684 
    1685 .is-embed.is-audio:before {
    1686         content: "\f127";
    1687 }
    1688 
    1689 .is-embed.is-tweet {
    1690         background-color: #55acee;
    1691 }
    1692 
    1693 .is-embed.is-tweet:before {
    1694         content: "\f301";
    1695 }
    1696 
    1697 .no-media {
    1698         margin: 0;
    1699         padding: 0;
    1700         border: 0;
    1701 }
    1702 
    1703 /* Actions bar */
    1704 .press-this-actions {
    1705         position: fixed;
    1706         bottom: 0;
    1707         left: 0;
    1708         width: 100%;
    1709         background: #f1f1f1;
    1710         background: rgba(241, 241, 241, 0.9);
    1711         border-top: 1px solid #e5e5e5;
    1712 }
    1713 
    1714 @media (max-width: 900px) {
    1715         .press-this-actions {
    1716                 -webkit-transform: translateY(0);
    1717                 transform: translateY(0);
    1718                 transition: -webkit-transform .3s ease-in-out;
    1719                 transition: transform .3s ease-in-out;
    1720                 transition: transform .3s ease-in-out, -webkit-transform .3s ease-in-out;
    1721         }
    1722         .press-this-actions.is-hidden {
    1723                 -webkit-transform: translateY(100%);
    1724                 transform: translateY(100%);
    1725         }
    1726 }
    1727 
    1728 .add-media {
    1729         float: left;
    1730         margin: 14px 0 14px 30px;
    1731         font-size: 0;
    1732 }
    1733 
    1734 @media (max-width: 320px) {
    1735         .add-media {
    1736                 margin: 10px 0 10px 10px;
    1737         }
    1738 }
    1739 
    1740 .insert-media {
    1741         color: #9ea7af;
    1742         float: left;
    1743         margin: 0;
    1744         padding: 0;
    1745         border: 0;
    1746         border-radius: 0;
    1747         background: none;
    1748         box-shadow: none;
    1749         overflow: hidden;
    1750 }
    1751 
    1752 .insert-media:hover,
    1753 .insert-media:focus,
    1754 .insert-media:active {
    1755         color: #23282d;
    1756 }
    1757 
    1758 .insert-media:focus,
    1759 .insert-media:active {
    1760         outline: 0;
    1761         color: #00a0d2;
    1762         box-shadow:
    1763                 0 0 0 1px #5b9dd9,
    1764                 0 0 2px 1px rgba(30, 140, 190, .8);
    1765 }
    1766 
    1767 .insert-media .dashicons {
    1768         padding: 11px;
    1769         width: 63px;
    1770         height: 58px;
    1771         font-size: 40px;
    1772 }
    1773 
    1774 @media (max-width: 320px) {
    1775         .insert-media .dashicons {
    1776                 width: 55px;
    1777                 height: 49px;
    1778                 padding: 14px;
    1779                 font-size: 20px;
    1780         }
    1781 }
    1782 
    1783 .post-actions {
    1784         float: right;
    1785         margin: 14px 30px 14px 0;
    1786         font-size: 13px;
    1787 }
    1788 
    1789 @media (max-width: 320px) {
    1790         .post-actions {
    1791                 margin: 10px 10px 10px 0;
    1792         }
    1793 }
    1794 
    1795 .publish-button .saving-draft,
    1796 .publish-button.is-saving .publish {
    1797         display: none;
    1798 }
    1799 
    1800 .publish-button.is-saving .saving-draft {
    1801         display: inline;
    1802 }
    1803 
    1804 /* TinyMCE styles */
    1805 .editor .wp-media-buttons {
    1806         float: none;
    1807 }
    1808 
    1809 .editor div.mce-toolbar-grp {
    1810         padding: 0.71429em 0;
    1811         background: none;
    1812         border: 0;
    1813 }
    1814 
    1815 @media (max-height: 400px), (max-width: 320px) {
    1816         .editor div.mce-toolbar-grp {
    1817                 padding: 0;
    1818         }
    1819 }
    1820 
    1821 .mce-stack-layout:before,
    1822 .mce-stack-layout:after {
    1823         content: "";
    1824         display: table;
    1825 }
    1826 
    1827 .mce-stack-layout:after {
    1828         clear: both;
    1829 }
    1830 
    1831 .mce-container.mce-toolbar {
    1832         float: left;
    1833 }
    1834 
    1835 .mce-container.mce-toolbar:nth-child(2) {
    1836         float: right;
    1837 }
    1838 
    1839 @media (max-width: 600px) {
    1840         .mce-first .mce-btn:nth-child(3),
    1841         .mce-first .mce-btn:nth-child(4) {
    1842                 position: absolute;
    1843                 margin: -1px;
    1844                 padding: 0;
    1845                 height: 1px;
    1846                 width: 1px;
    1847                 overflow: hidden;
    1848                 clip: rect(0 0 0 0);
    1849                 border: 0;
    1850         }
    1851 
    1852         .mce-first .mce-btn:nth-child(3):focus,
    1853         .mce-first .mce-btn:nth-child(4):focus {
    1854                 position: static;
    1855                 margin: 1px;
    1856                 padding: inherit;
    1857                 height: auto;
    1858                 width: auto;
    1859                 overflow: visible;
    1860                 clip: auto;
    1861                 border: 1px solid #999;
    1862         }
    1863 }
    1864 
    1865 #wp-link-wrap {
    1866         font-size: 13px;
    1867 }
    1868 
    1869 #wp-link-wrap input[type="text"] {
    1870         padding: 3px 5px;
    1871         margin: 1px;
    1872 }
    1873 
    1874 @media screen and (max-width: 782px) {
    1875         #wp-link-wrap {
    1876                 font-size: 14px;
    1877         }
    1878 
    1879         #wp-link-wrap input[type="text"] {
    1880                 padding: 6px 10px;
    1881         }
    1882 }
    1883 
    1884 #wp-link-wrap .howto {
    1885         color: #666;
    1886         font-style: italic;
    1887 }
    1888 
    1889 /* Options panel (sidebar) */
    1890 .options-panel {
    1891         position: relative;
    1892         float: right;
    1893         margin-right: -320px;
    1894         width: 320px;
    1895         border-left: 1px solid #e5e5e5;
    1896         font-size: 14px;
    1897         /* Keeps background the full height of the screen, but only visually. Clicks go through. */
    1898         box-shadow: 5001px 5000px 0 5000px #fff, 5000px 5000px 0 5000px #e5e5e5;
    1899         outline: 0;
    1900 }
    1901 
    1902 .options-panel-back {
    1903         position: absolute;
    1904         top: 0;
    1905         right: 0;
    1906         bottom: 0;
    1907         width: 320px;
    1908         outline: 0;
    1909 }
    1910 
    1911 @media (max-width: 900px) {
    1912         .options-panel {
    1913                 background: #fff;
    1914                 -webkit-transform: translateX(-100%);
    1915                 transform: translateX(-100%);
    1916                 transition: -webkit-transform .3s ease-in-out;
    1917                 transition: transform .3s ease-in-out;
    1918                 transition: transform .3s ease-in-out, -webkit-transform .3s ease-in-out;
    1919         }
    1920 
    1921         .options-panel.is-hidden {
    1922                 visibility: hidden;
    1923         }
    1924 
    1925         .options-panel.is-off-screen {
    1926                 -webkit-transform: translateX(0);
    1927                 transform: translateX(0);
    1928         }
    1929 }
    1930 
    1931 @media (max-width: 320px) {
    1932         .options-panel {
    1933                 margin-right: -100%;
    1934                 width: 100%;
    1935                 border: 0;
    1936                 box-shadow: 5001px 5000px 0 5000px #fff;
    1937         }
    1938 
    1939         .options-panel-back {
    1940                 width: 100%;
    1941         }
    1942 }
    1943 
    1944 .post-options {
    1945         background: #fff;
    1946         position: absolute;
    1947         right: 0;
    1948         width: 100%;
    1949         overflow-x: hidden;
    1950 }
    1951 
    1952 .post-options .post-option-contents {
    1953         margin-left: 3px;
    1954         color: #32373c;
    1955 }
    1956 
    1957 .post-option-forward:before {
    1958         position: absolute;
    1959         top: 50%;
    1960         right: 8px;
    1961         margin-top: -10px;
    1962         content: "\f345"
    1963 }
    1964 
    1965 .post-option-back:before {
    1966         content: "\f341";
    1967 }
    1968 
    1969 .lt-ie9 .options-panel,
    1970 .lt-ie9 .post-options {
    1971         border-left: 1px solid #e5e5e5;
    1972 }
    1973 
    1974 .lt-ie9 .post-options.is-off-screen {
    1975         border: 0;
    1976 }
    1977 
    1978 .post-option {
    1979         position: relative;
    1980 }
    1981 
    1982 .post-options .post-option {
    1983         display: block;
    1984         width: 100%;
    1985         margin: 0;
    1986         padding: 13px 37px 13px 14px;
    1987         border: 0;
    1988         border-bottom: 1px solid #e5e5e5;
    1989         text-decoration: none;
    1990         text-align: left;
    1991         background: none;
    1992         color: #9ea7af;
    1993         text-overflow: ellipsis;
    1994         white-space: nowrap;
    1995         overflow: hidden;
    1996         transition: -webkit-transform .3s ease-in-out;
    1997         transition: transform .3s ease-in-out;
    1998         transition: transform .3s ease-in-out, -webkit-transform .3s ease-in-out;
    1999 }
    2000 
    2001 .post-options .post-option:focus {
    2002         outline: 0;
    2003         box-shadow: inset 5px 0 0 #00a0d2;
    2004         border-color: #e5e5e5;
    2005 }
    2006 
    2007 .is-off-screen > .post-option {
    2008         right: 100%;
    2009 }
    2010 
    2011 .is-hidden > .post-option {
    2012         visibility: hidden;
    2013 }
    2014 
    2015 @media (min-width: 1px) {
    2016         .is-off-screen > .post-option {
    2017                 right: auto;
    2018                 -webkit-transform: translateX(-100%);
    2019                 transform: translateX(-100%);
    2020         }
    2021 }
    2022 
    2023 .post-option-title {
    2024         display: inline-block;
    2025         margin: 0 0 0 8px;
    2026         font-size: 14px;
    2027         font-weight: 400;
    2028 }
    2029 
    2030 .setting-modal {
    2031         position: relative;
    2032         top: 0;
    2033         left: 0;
    2034         width: 100%;
    2035         overflow: hidden;
    2036         transition: -webkit-transform .3s ease-in-out;
    2037         transition: transform .3s ease-in-out;
    2038         transition: transform .3s ease-in-out, -webkit-transform .3s ease-in-out;
    2039 }
    2040 
    2041 .setting-modal.is-hidden {
    2042         visibility: hidden;
    2043         height: 0;
    2044 }
    2045 
    2046 .setting-modal.is-off-screen {
    2047         left: 100%;
    2048 }
    2049 
    2050 @media (min-width: 1px) {
    2051         .setting-modal.is-off-screen {
    2052                 left: 0;
    2053                 -webkit-transform: translateX(100%);
    2054                 transform: translateX(100%);
    2055         }
    2056 }
    2057 
    2058 .press-this .modal-close {
    2059         display: block;
    2060         width: 100%;
    2061         padding: 13px 14px;
    2062         border: 0;
    2063         border-bottom: 1px solid #e5e5e5;
    2064         background: none;
    2065         color: #00a0d2;
    2066         text-decoration: none;
    2067         text-align: left;
    2068 }
    2069 
    2070 .press-this .modal-close:focus {
    2071         outline: 0;
    2072         box-shadow: inset 5px 0 0 #00a0d2;
    2073         border-color: #e5e5e5;
    2074 }
    2075 
    2076 .setting-title {
    2077         position: relative;
    2078         top: -1px;
    2079         margin-left: 11px;
    2080 }
    2081 
    2082 /* Text editor */
    2083 #pressthis {
    2084         color: #404040;
    2085         resize: none;
    2086         padding-top: 30px;
    2087         font-size: 16px;
    2088 }
    2089 
    2090 .wp-editor-wrap .quicktags-toolbar {
    2091         background: transparent;
    2092         border: none;
    2093 }
    2094 
    2095 /* Switch editor buttons */
    2096 .wp-editor-wrap .wp-editor-tools {
    2097         z-index: 0;
    2098 }
    2099 
    2100 .wp-editor-wrap .wp-editor-tabs {
    2101         padding: 2px;
    2102 }
    2103 
    2104 .wp-editor-wrap .wp-switch-editor {
    2105         top: 0;
    2106         margin: 3px 0 0 5px;
    2107         padding: 3px 8px;
    2108         background: #f5f5f5;
    2109         color: #555;
    2110         border-color: #ccc;
    2111 }
    2112 
    2113 .wp-editor-wrap .wp-switch-editor:hover {
    2114         background: #fafafa;
    2115         border-color: #999;
    2116         color: #23282d;
    2117 }
    2118 
    2119 .wp-editor-wrap.tmce-active .switch-tmce,
    2120 .wp-editor-wrap.html-active .switch-html {
    2121         background: #fff;
    2122         border-color: #d8d8d8;
    2123 }
    2124 
    2125 /* Inline link dialog */
    2126 .wp-link-input input {
    2127         border: 1px solid #ddd;
    2128     box-shadow: inset 0 1px 2px rgba( 0, 0, 0, 0.07 );
    2129     background-color: #fff;
    2130     color: #32373c;
    2131     outline: none;
    2132     transition: 0.05s border-color ease-in-out;
    2133 }
    2134 
    2135 /* UI Autocomplete (for inline link and wpLink) */
    2136 .ui-autocomplete {
    2137         padding: 0;
    2138         margin: 0;
    2139         list-style: none;
    2140         position: absolute;
    2141         z-index: 10000;
    2142         border: 1px solid #5b9dd9;
    2143         box-shadow: 0 1px 2px rgba( 30, 140, 190, 0.8 );
    2144         background-color: #fff;
    2145         font-size: 14px;
    2146 }
    2147 
    2148 .ui-autocomplete li {
    2149         margin-bottom: 0;
    2150         padding: 4px 10px;
    2151         white-space: nowrap;
    2152         text-align: left;
    2153         cursor: pointer;
    2154 }
    2155 
    2156 /* Colors for the wplink toolbar autocomplete. */
    2157 .ui-autocomplete .ui-state-focus {
    2158         background-color: #ddd;
    2159 }
    2160 
    2161 /* Colors for the tags autocomplete. */
    2162 .wp-tags-autocomplete .ui-state-focus {
    2163         background-color: #0073aa;
    2164         color: #fff;
    2165 }
  • src/wp-admin/includes/ajax-actions.php

    diff --git src/wp-admin/includes/ajax-actions.php src/wp-admin/includes/ajax-actions.php
    index 3f3c0fc7e8..24eb77702a 100644
    function wp_ajax_destroy_sessions() { 
    31893189}
    31903190
    31913191/**
    3192  * Ajax handler for saving a post from Press This.
    3193  *
    3194  * @since 4.2.0
    3195  */
    3196 function wp_ajax_press_this_save_post() {
    3197         include( ABSPATH . 'wp-admin/includes/class-wp-press-this.php' );
    3198         $wp_press_this = new WP_Press_This();
    3199         $wp_press_this->save_post();
    3200 }
    3201 
    3202 /**
    3203  * Ajax handler for creating new category from Press This.
    3204  *
    3205  * @since 4.2.0
    3206  */
    3207 function wp_ajax_press_this_add_category() {
    3208         include( ABSPATH . 'wp-admin/includes/class-wp-press-this.php' );
    3209         $wp_press_this = new WP_Press_This();
    3210         $wp_press_this->add_category();
    3211 }
    3212 
    3213 /**
    32143192 * Ajax handler for cropping an image.
    32153193 *
    32163194 * @since 4.3.0
  • src/wp-admin/includes/class-plugin-installer-skin.php

    diff --git src/wp-admin/includes/class-plugin-installer-skin.php src/wp-admin/includes/class-plugin-installer-skin.php
    index d179fde67f..66f406227b 100644
    class Plugin_Installer_Skin extends WP_Upgrader_Skin { 
    4949
    5050                $from = isset($_GET['from']) ? wp_unslash( $_GET['from'] ) : 'plugins';
    5151
    52                 if ( 'import' == $from )
     52                if ( 'import' == $from ) {
    5353                        $install_actions['activate_plugin'] = '<a class="button button-primary" href="' . wp_nonce_url( 'plugins.php?action=activate&amp;from=import&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ) . '" target="_parent">' . __( 'Activate Plugin &amp; Run Importer' ) . '</a>';
    54                 else
     54                } else if ( 'press-this' == $from ) {
     55                        $install_actions['activate_plugin'] = '<a class="button button-primary" href="' . wp_nonce_url( 'plugins.php?action=activate&amp;from=press-this&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ) . '" target="_parent">' . __( 'Activate Plugin &amp; Return to Press This' ) . '</a>';
     56                } else {
    5557                        $install_actions['activate_plugin'] = '<a class="button button-primary" href="' . wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ) . '" target="_parent">' . __( 'Activate Plugin' ) . '</a>';
     58                }
    5659
    5760                if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
    5861                        $install_actions['network_activate'] = '<a class="button button-primary" href="' . wp_nonce_url( 'plugins.php?action=activate&amp;networkwide=1&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ) . '" target="_parent">' . __( 'Network Activate' ) . '</a>';
  • deleted file src/wp-admin/includes/class-wp-press-this.php

    diff --git src/wp-admin/includes/class-wp-press-this.php src/wp-admin/includes/class-wp-press-this.php
    deleted file mode 100644
    index 7f268ea028..0000000000
    + -  
    1 <?php
    2 /**
    3  * Press This class and display functionality
    4  *
    5  * @package WordPress
    6  * @subpackage Press_This
    7  * @since 4.2.0
    8  */
    9 
    10 /**
    11  * Press This class.
    12  *
    13  * @since 4.2.0
    14  */
    15 class WP_Press_This {
    16         // Used to trigger the bookmarklet update notice.
    17         const VERSION = 8;
    18         public $version = 8;
    19 
    20         private $images = array();
    21 
    22         private $embeds = array();
    23 
    24         private $domain = '';
    25 
    26         /**
    27          * Constructor.
    28          *
    29          * @since 4.2.0
    30          */
    31         public function __construct() {}
    32 
    33         /**
    34          * App and site settings data, including i18n strings for the client-side.
    35          *
    36          * @since 4.2.0
    37          *
    38          * @return array Site settings.
    39          */
    40         public function site_settings() {
    41                 return array(
    42                         /**
    43                          * Filters whether or not Press This should redirect the user in the parent window upon save.
    44                          *
    45                          * @since 4.2.0
    46                          *
    47                          * @param bool $redirect Whether to redirect in parent window or not. Default false.
    48                          */
    49                         'redirInParent' => apply_filters( 'press_this_redirect_in_parent', false ),
    50                 );
    51         }
    52 
    53         /**
    54          * Get the source's images and save them locally, for posterity, unless we can't.
    55          *
    56          * @since 4.2.0
    57          *
    58          * @param int    $post_id Post ID.
    59          * @param string $content Optional. Current expected markup for Press This. Expects slashed. Default empty.
    60          * @return string New markup with old image URLs replaced with the local attachment ones if swapped.
    61          */
    62         public function side_load_images( $post_id, $content = '' ) {
    63                 $content = wp_unslash( $content );
    64 
    65                 if ( preg_match_all( '/<img [^>]+>/', $content, $matches ) && current_user_can( 'upload_files' ) ) {
    66                         foreach ( (array) $matches[0] as $image ) {
    67                                 // This is inserted from our JS so HTML attributes should always be in double quotes.
    68                                 if ( ! preg_match( '/src="([^"]+)"/', $image, $url_matches ) ) {
    69                                         continue;
    70                                 }
    71 
    72                                 $image_src = $url_matches[1];
    73 
    74                                 // Don't try to sideload a file without a file extension, leads to WP upload error.
    75                                 if ( ! preg_match( '/[^\?]+\.(?:jpe?g|jpe|gif|png)(?:\?|$)/i', $image_src ) ) {
    76                                         continue;
    77                                 }
    78 
    79                                 // Sideload image, which gives us a new image src.
    80                                 $new_src = media_sideload_image( $image_src, $post_id, null, 'src' );
    81 
    82                                 if ( ! is_wp_error( $new_src ) ) {
    83                                         // Replace the POSTED content <img> with correct uploaded ones.
    84                                         // Need to do it in two steps so we don't replace links to the original image if any.
    85                                         $new_image = str_replace( $image_src, $new_src, $image );
    86                                         $content = str_replace( $image, $new_image, $content );
    87                                 }
    88                         }
    89                 }
    90 
    91                 // Expected slashed
    92                 return wp_slash( $content );
    93         }
    94 
    95         /**
    96          * Ajax handler for saving the post as draft or published.
    97          *
    98          * @since 4.2.0
    99          */
    100         public function save_post() {
    101                 if ( empty( $_POST['post_ID'] ) || ! $post_id = (int) $_POST['post_ID'] ) {
    102                         wp_send_json_error( array( 'errorMessage' => __( 'Missing post ID.' ) ) );
    103                 }
    104 
    105                 if ( empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'update-post_' . $post_id ) ||
    106                         ! current_user_can( 'edit_post', $post_id ) ) {
    107 
    108                         wp_send_json_error( array( 'errorMessage' => __( 'Invalid post.' ) ) );
    109                 }
    110 
    111                 $post_data = array(
    112                         'ID'            => $post_id,
    113                         'post_title'    => ( ! empty( $_POST['post_title'] ) ) ? sanitize_text_field( trim( $_POST['post_title'] ) ) : '',
    114                         'post_content'  => ( ! empty( $_POST['post_content'] ) ) ? trim( $_POST['post_content'] ) : '',
    115                         'post_type'     => 'post',
    116                         'post_status'   => 'draft',
    117                         'post_format'   => ( ! empty( $_POST['post_format'] ) ) ? sanitize_text_field( $_POST['post_format'] ) : '',
    118                 );
    119 
    120                 // Only accept categories if the user actually can assign
    121                 $category_tax = get_taxonomy( 'category' );
    122                 if ( current_user_can( $category_tax->cap->assign_terms ) ) {
    123                         $post_data['post_category'] = ( ! empty( $_POST['post_category'] ) ) ? $_POST['post_category'] : array();
    124                 }
    125 
    126                 // Only accept taxonomies if the user can actually assign
    127                 if ( ! empty( $_POST['tax_input'] ) ) {
    128                         $tax_input = $_POST['tax_input'];
    129                         foreach ( $tax_input as $tax => $_ti ) {
    130                                 $tax_object = get_taxonomy( $tax );
    131                                 if ( ! $tax_object || ! current_user_can( $tax_object->cap->assign_terms ) ) {
    132                                         unset( $tax_input[ $tax ] );
    133                                 }
    134                         }
    135 
    136                         $post_data['tax_input'] = $tax_input;
    137                 }
    138 
    139                 // Toggle status to pending if user cannot actually publish
    140                 if ( ! empty( $_POST['post_status'] ) && 'publish' === $_POST['post_status'] ) {
    141                         if ( current_user_can( 'publish_posts' ) ) {
    142                                 $post_data['post_status'] = 'publish';
    143                         } else {
    144                                 $post_data['post_status'] = 'pending';
    145                         }
    146                 }
    147 
    148                 $post_data['post_content'] = $this->side_load_images( $post_id, $post_data['post_content'] );
    149 
    150                 /**
    151                  * Filters the post data of a Press This post before saving/updating.
    152                  *
    153                  * The {@see 'side_load_images'} action has already run at this point.
    154                  *
    155                  * @since 4.5.0
    156                  *
    157                  * @param array $post_data The post data.
    158                  */
    159                 $post_data = apply_filters( 'press_this_save_post', $post_data );
    160 
    161                 $updated = wp_update_post( $post_data, true );
    162 
    163                 if ( is_wp_error( $updated ) ) {
    164                         wp_send_json_error( array( 'errorMessage' => $updated->get_error_message() ) );
    165                 } else {
    166                         if ( isset( $post_data['post_format'] ) ) {
    167                                 if ( current_theme_supports( 'post-formats', $post_data['post_format'] ) ) {
    168                                         set_post_format( $post_id, $post_data['post_format'] );
    169                                 } elseif ( $post_data['post_format'] ) {
    170                                         set_post_format( $post_id, false );
    171                                 }
    172                         }
    173 
    174                         $forceRedirect = false;
    175 
    176                         if ( 'publish' === get_post_status( $post_id ) ) {
    177                                 $redirect = get_post_permalink( $post_id );
    178                         } elseif ( isset( $_POST['pt-force-redirect'] ) && $_POST['pt-force-redirect'] === 'true' ) {
    179                                 $forceRedirect = true;
    180                                 $redirect = get_edit_post_link( $post_id, 'js' );
    181                         } else {
    182                                 $redirect = false;
    183                         }
    184 
    185                         /**
    186                          * Filters the URL to redirect to when Press This saves.
    187                          *
    188                          * @since 4.2.0
    189                          *
    190                          * @param string $url     Redirect URL. If `$status` is 'publish', this will be the post permalink.
    191                          *                        Otherwise, the default is false resulting in no redirect.
    192                          * @param int    $post_id Post ID.
    193                          * @param string $status  Post status.
    194                          */
    195                         $redirect = apply_filters( 'press_this_save_redirect', $redirect, $post_id, $post_data['post_status'] );
    196 
    197                         if ( $redirect ) {
    198                                 wp_send_json_success( array( 'redirect' => $redirect, 'force' => $forceRedirect ) );
    199                         } else {
    200                                 wp_send_json_success( array( 'postSaved' => true ) );
    201                         }
    202                 }
    203         }
    204 
    205         /**
    206          * Ajax handler for adding a new category.
    207          *
    208          * @since 4.2.0
    209          */
    210         public function add_category() {
    211                 if ( false === wp_verify_nonce( $_POST['new_cat_nonce'], 'add-category' ) ) {
    212                         wp_send_json_error();
    213                 }
    214 
    215                 $taxonomy = get_taxonomy( 'category' );
    216 
    217                 if ( ! current_user_can( $taxonomy->cap->edit_terms ) || empty( $_POST['name'] ) ) {
    218                         wp_send_json_error();
    219                 }
    220 
    221                 $parent = isset( $_POST['parent'] ) && (int) $_POST['parent'] > 0 ? (int) $_POST['parent'] : 0;
    222                 $names = explode( ',', $_POST['name'] );
    223                 $added = $data = array();
    224 
    225                 foreach ( $names as $cat_name ) {
    226                         $cat_name = trim( $cat_name );
    227                         $cat_nicename = sanitize_title( $cat_name );
    228 
    229                         if ( empty( $cat_nicename ) ) {
    230                                 continue;
    231                         }
    232 
    233                         // @todo Find a more performant way to check existence, maybe get_term() with a separate parent check.
    234                         if ( term_exists( $cat_name, $taxonomy->name, $parent ) ) {
    235                                 if ( count( $names ) === 1 ) {
    236                                         wp_send_json_error( array( 'errorMessage' => __( 'This category already exists.' ) ) );
    237                                 } else {
    238                                         continue;
    239                                 }
    240                         }
    241 
    242                         $cat_id = wp_insert_term( $cat_name, $taxonomy->name, array( 'parent' => $parent ) );
    243 
    244                         if ( is_wp_error( $cat_id ) ) {
    245                                 continue;
    246                         } elseif ( is_array( $cat_id ) ) {
    247                                 $cat_id = $cat_id['term_id'];
    248                         }
    249 
    250                         $added[] = $cat_id;
    251                 }
    252 
    253                 if ( empty( $added ) ) {
    254                         wp_send_json_error( array( 'errorMessage' => __( 'This category cannot be added. Please change the name and try again.' ) ) );
    255                 }
    256 
    257                 foreach ( $added as $new_cat_id ) {
    258                         $new_cat = get_category( $new_cat_id );
    259 
    260                         if ( is_wp_error( $new_cat ) ) {
    261                                 wp_send_json_error( array( 'errorMessage' => __( 'Error while adding the category. Please try again later.' ) ) );
    262                         }
    263 
    264                         $data[] = array(
    265                                 'term_id' => $new_cat->term_id,
    266                                 'name' => $new_cat->name,
    267                                 'parent' => $new_cat->parent,
    268                         );
    269                 }
    270                 wp_send_json_success( $data );
    271         }
    272 
    273         /**
    274          * Downloads the source's HTML via server-side call for the given URL.
    275          *
    276          * @since 4.2.0
    277          *
    278          * @param string $url URL to scan.
    279          * @return string Source's HTML sanitized markup
    280          */
    281         public function fetch_source_html( $url ) {
    282                 if ( empty( $url ) ) {
    283                         return new WP_Error( 'invalid-url', __( 'A valid URL was not provided.' ) );
    284                 }
    285 
    286                 $remote_url = wp_safe_remote_get( $url, array(
    287                         'timeout' => 30,
    288                         // Use an explicit user-agent for Press This
    289                         'user-agent' => 'Press This (WordPress/' . get_bloginfo( 'version' ) . '); ' . get_bloginfo( 'url' )
    290                 ) );
    291 
    292                 if ( is_wp_error( $remote_url ) ) {
    293                         return $remote_url;
    294                 }
    295 
    296                 $allowed_elements = array(
    297                         'img' => array(
    298                                 'src'      => true,
    299                                 'width'    => true,
    300                                 'height'   => true,
    301                         ),
    302                         'iframe' => array(
    303                                 'src'      => true,
    304                         ),
    305                         'link' => array(
    306                                 'rel'      => true,
    307                                 'itemprop' => true,
    308                                 'href'     => true,
    309                         ),
    310                         'meta' => array(
    311                                 'property' => true,
    312                                 'name'     => true,
    313                                 'content'  => true,
    314                         )
    315                 );
    316 
    317                 $source_content = wp_remote_retrieve_body( $remote_url );
    318                 $source_content = wp_kses( $source_content, $allowed_elements );
    319 
    320                 return $source_content;
    321         }
    322 
    323         /**
    324          * Utility method to limit an array to 50 values.
    325          *
    326          * @ignore
    327          * @since 4.2.0
    328          *
    329          * @param array $value Array to limit.
    330          * @return array Original array if fewer than 50 values, limited array, empty array otherwise.
    331          */
    332         private function _limit_array( $value ) {
    333                 if ( is_array( $value ) ) {
    334                         if ( count( $value ) > 50 ) {
    335                                 return array_slice( $value, 0, 50 );
    336                         }
    337 
    338                         return $value;
    339                 }
    340 
    341                 return array();
    342         }
    343 
    344         /**
    345          * Utility method to limit the length of a given string to 5,000 characters.
    346          *
    347          * @ignore
    348          * @since 4.2.0
    349          *
    350          * @param string $value String to limit.
    351          * @return bool|int|string If boolean or integer, that value. If a string, the original value
    352          *                         if fewer than 5,000 characters, a truncated version, otherwise an
    353          *                         empty string.
    354          */
    355         private function _limit_string( $value ) {
    356                 $return = '';
    357 
    358                 if ( is_numeric( $value ) || is_bool( $value ) ) {
    359                         $return = $value;
    360                 } else if ( is_string( $value ) ) {
    361                         if ( mb_strlen( $value ) > 5000 ) {
    362                                 $return = mb_substr( $value, 0, 5000 );
    363                         } else {
    364                                 $return = $value;
    365                         }
    366 
    367                         $return = html_entity_decode( $return, ENT_QUOTES, 'UTF-8' );
    368                         $return = sanitize_text_field( trim( $return ) );
    369                 }
    370 
    371                 return $return;
    372         }
    373 
    374         /**
    375          * Utility method to limit a given URL to 2,048 characters.
    376          *
    377          * @ignore
    378          * @since 4.2.0
    379          *
    380          * @param string $url URL to check for length and validity.
    381          * @return string Escaped URL if of valid length (< 2048) and makeup. Empty string otherwise.
    382          */
    383         private function _limit_url( $url ) {
    384                 if ( ! is_string( $url ) ) {
    385                         return '';
    386                 }
    387 
    388                 // HTTP 1.1 allows 8000 chars but the "de-facto" standard supported in all current browsers is 2048.
    389                 if ( strlen( $url ) > 2048 ) {
    390                         return ''; // Return empty rather than a truncated/invalid URL
    391                 }
    392 
    393                 // Does not look like a URL.
    394                 if ( ! preg_match( '/^([!#$&-;=?-\[\]_a-z~]|%[0-9a-fA-F]{2})+$/', $url ) ) {
    395                         return '';
    396                 }
    397 
    398                 // If the URL is root-relative, prepend the protocol and domain name
    399                 if ( $url && $this->domain && preg_match( '%^/[^/]+%', $url ) ) {
    400                         $url = $this->domain . $url;
    401                 }
    402 
    403                 // Not absolute or protocol-relative URL.
    404                 if ( ! preg_match( '%^(?:https?:)?//[^/]+%', $url ) ) {
    405                         return '';
    406                 }
    407 
    408                 return esc_url_raw( $url, array( 'http', 'https' ) );
    409         }
    410 
    411         /**
    412          * Utility method to limit image source URLs.
    413          *
    414          * Excluded URLs include share-this type buttons, loaders, spinners, spacers, WordPress interface images,
    415          * tiny buttons or thumbs, mathtag.com or quantserve.com images, or the WordPress.com stats gif.
    416          *
    417          * @ignore
    418          * @since 4.2.0
    419          *
    420          * @param string $src Image source URL.
    421          * @return string If not matched an excluded URL type, the original URL, empty string otherwise.
    422          */
    423         private function _limit_img( $src ) {
    424                 $src = $this->_limit_url( $src );
    425 
    426                 if ( preg_match( '!/ad[sx]?/!i', $src ) ) {
    427                         // Ads
    428                         return '';
    429                 } else if ( preg_match( '!(/share-?this[^.]+?\.[a-z0-9]{3,4})(\?.*)?$!i', $src ) ) {
    430                         // Share-this type button
    431                         return '';
    432                 } else if ( preg_match( '!/(spinner|loading|spacer|blank|rss)\.(gif|jpg|png)!i', $src ) ) {
    433                         // Loaders, spinners, spacers
    434                         return '';
    435                 } else if ( preg_match( '!/([^./]+[-_])?(spinner|loading|spacer|blank)s?([-_][^./]+)?\.[a-z0-9]{3,4}!i', $src ) ) {
    436                         // Fancy loaders, spinners, spacers
    437                         return '';
    438                 } else if ( preg_match( '!([^./]+[-_])?thumb[^.]*\.(gif|jpg|png)$!i', $src ) ) {
    439                         // Thumbnails, too small, usually irrelevant to context
    440                         return '';
    441                 } else if ( false !== stripos( $src, '/wp-includes/' ) ) {
    442                         // Classic WordPress interface images
    443                         return '';
    444                 } else if ( preg_match( '![^\d]\d{1,2}x\d+\.(gif|jpg|png)$!i', $src ) ) {
    445                         // Most often tiny buttons/thumbs (< 100px wide)
    446                         return '';
    447                 } else if ( preg_match( '!/pixel\.(mathtag|quantserve)\.com!i', $src ) ) {
    448                         // See mathtag.com and https://www.quantcast.com/how-we-do-it/iab-standard-measurement/how-we-collect-data/
    449                         return '';
    450                 } else if ( preg_match( '!/[gb]\.gif(\?.+)?$!i', $src ) ) {
    451                         // WordPress.com stats gif
    452                         return '';
    453                 }
    454 
    455                 return $src;
    456         }
    457 
    458         /**
    459          * Limit embed source URLs to specific providers.
    460          *
    461          * Not all core oEmbed providers are supported. Supported providers include YouTube, Vimeo,
    462          * Daily Motion, SoundCloud, and Twitter.
    463          *
    464          * @ignore
    465          * @since 4.2.0
    466          *
    467          * @param string $src Embed source URL.
    468          * @return string If not from a supported provider, an empty string. Otherwise, a reformatted embed URL.
    469          */
    470         private function _limit_embed( $src ) {
    471                 $src = $this->_limit_url( $src );
    472 
    473                 if ( empty( $src ) )
    474                         return '';
    475 
    476                 if ( preg_match( '!//(m|www)\.youtube\.com/(embed|v)/([^?]+)\?.+$!i', $src, $src_matches ) ) {
    477                         // Embedded Youtube videos (www or mobile)
    478                         $src = 'https://www.youtube.com/watch?v=' . $src_matches[3];
    479                 } else if ( preg_match( '!//player\.vimeo\.com/video/([\d]+)([?/].*)?$!i', $src, $src_matches ) ) {
    480                         // Embedded Vimeo iframe videos
    481                         $src = 'https://vimeo.com/' . (int) $src_matches[1];
    482                 } else if ( preg_match( '!//vimeo\.com/moogaloop\.swf\?clip_id=([\d]+)$!i', $src, $src_matches ) ) {
    483                         // Embedded Vimeo Flash videos
    484                         $src = 'https://vimeo.com/' . (int) $src_matches[1];
    485                 } else if ( preg_match( '!//(www\.)?dailymotion\.com/embed/video/([^/?]+)([/?].+)?!i', $src, $src_matches ) ) {
    486                         // Embedded Daily Motion videos
    487                         $src = 'https://www.dailymotion.com/video/' . $src_matches[2];
    488                 } else {
    489                         $oembed = _wp_oembed_get_object();
    490 
    491                         if ( ! $oembed->get_provider( $src, array( 'discover' => false ) ) ) {
    492                                 $src = '';
    493                         }
    494                 }
    495 
    496                 return $src;
    497         }
    498 
    499         /**
    500          * Process a meta data entry from the source.
    501          *
    502          * @ignore
    503          * @since 4.2.0
    504          *
    505          * @param string $meta_name  Meta key name.
    506          * @param mixed  $meta_value Meta value.
    507          * @param array  $data       Associative array of source data.
    508          * @return array Processed data array.
    509          */
    510         private function _process_meta_entry( $meta_name, $meta_value, $data ) {
    511                 if ( preg_match( '/:?(title|description|keywords|site_name)$/', $meta_name ) ) {
    512                         $data['_meta'][ $meta_name ] = $meta_value;
    513                 } else {
    514                         switch ( $meta_name ) {
    515                                 case 'og:url':
    516                                 case 'og:video':
    517                                 case 'og:video:secure_url':
    518                                         $meta_value = $this->_limit_embed( $meta_value );
    519 
    520                                         if ( ! isset( $data['_embeds'] ) ) {
    521                                                 $data['_embeds'] = array();
    522                                         }
    523 
    524                                         if ( ! empty( $meta_value ) && ! in_array( $meta_value, $data['_embeds'] ) ) {
    525                                                 $data['_embeds'][] = $meta_value;
    526                                         }
    527 
    528                                         break;
    529                                 case 'og:image':
    530                                 case 'og:image:secure_url':
    531                                 case 'twitter:image0:src':
    532                                 case 'twitter:image0':
    533                                 case 'twitter:image:src':
    534                                 case 'twitter:image':
    535                                         $meta_value = $this->_limit_img( $meta_value );
    536 
    537                                         if ( ! isset( $data['_images'] ) ) {
    538                                                 $data['_images'] = array();
    539                                         }
    540 
    541                                         if ( ! empty( $meta_value ) && ! in_array( $meta_value, $data['_images'] ) ) {
    542                                                 $data['_images'][] = $meta_value;
    543                                         }
    544 
    545                                         break;
    546                         }
    547                 }
    548 
    549                 return $data;
    550         }
    551 
    552         /**
    553          * Fetches and parses _meta, _images, and _links data from the source.
    554          *
    555          * @since 4.2.0
    556          *
    557          * @param string $url  URL to scan.
    558          * @param array  $data Optional. Existing data array if you have one. Default empty array.
    559          * @return array New data array.
    560          */
    561         public function source_data_fetch_fallback( $url, $data = array() ) {
    562                 if ( empty( $url ) ) {
    563                         return array();
    564                 }
    565 
    566                 // Download source page to tmp file.
    567                 $source_content = $this->fetch_source_html( $url );
    568                 if ( is_wp_error( $source_content ) ) {
    569                         return array( 'errors' => $source_content->get_error_messages() );
    570                 }
    571 
    572                 // Fetch and gather <meta> data first, so discovered media is offered 1st to user.
    573                 if ( empty( $data['_meta'] ) ) {
    574                         $data['_meta'] = array();
    575                 }
    576 
    577                 if ( preg_match_all( '/<meta [^>]+>/', $source_content, $matches ) ) {
    578                         $items = $this->_limit_array( $matches[0] );
    579 
    580                         foreach ( $items as $value ) {
    581                                 if ( preg_match( '/(property|name)="([^"]+)"[^>]+content="([^"]+)"/', $value, $new_matches ) ) {
    582                                         $meta_name  = $this->_limit_string( $new_matches[2] );
    583                                         $meta_value = $this->_limit_string( $new_matches[3] );
    584 
    585                                         // Sanity check. $key is usually things like 'title', 'description', 'keywords', etc.
    586                                         if ( strlen( $meta_name ) > 100 ) {
    587                                                 continue;
    588                                         }
    589 
    590                                         $data = $this->_process_meta_entry( $meta_name, $meta_value, $data );
    591                                 }
    592                         }
    593                 }
    594 
    595                 // Fetch and gather <img> data.
    596                 if ( empty( $data['_images'] ) ) {
    597                         $data['_images'] = array();
    598                 }
    599 
    600                 if ( preg_match_all( '/<img [^>]+>/', $source_content, $matches ) ) {
    601                         $items = $this->_limit_array( $matches[0] );
    602 
    603                         foreach ( $items as $value ) {
    604                                 if ( ( preg_match( '/width=(\'|")(\d+)\\1/i', $value, $new_matches ) && $new_matches[2] < 256 ) ||
    605                                         ( preg_match( '/height=(\'|")(\d+)\\1/i', $value, $new_matches ) && $new_matches[2] < 128 ) ) {
    606 
    607                                         continue;
    608                                 }
    609 
    610                                 if ( preg_match( '/src=(\'|")([^\'"]+)\\1/i', $value, $new_matches ) ) {
    611                                         $src = $this->_limit_img( $new_matches[2] );
    612                                         if ( ! empty( $src ) && ! in_array( $src, $data['_images'] ) ) {
    613                                                 $data['_images'][] = $src;
    614                                         }
    615                                 }
    616                         }
    617                 }
    618 
    619                 // Fetch and gather <iframe> data.
    620                 if ( empty( $data['_embeds'] ) ) {
    621                         $data['_embeds'] = array();
    622                 }
    623 
    624                 if ( preg_match_all( '/<iframe [^>]+>/', $source_content, $matches ) ) {
    625                         $items = $this->_limit_array( $matches[0] );
    626 
    627                         foreach ( $items as $value ) {
    628                                 if ( preg_match( '/src=(\'|")([^\'"]+)\\1/', $value, $new_matches ) ) {
    629                                         $src = $this->_limit_embed( $new_matches[2] );
    630 
    631                                         if ( ! empty( $src ) && ! in_array( $src, $data['_embeds'] ) ) {
    632                                                 $data['_embeds'][] = $src;
    633                                         }
    634                                 }
    635                         }
    636                 }
    637 
    638                 // Fetch and gather <link> data.
    639                 if ( empty( $data['_links'] ) ) {
    640                         $data['_links'] = array();
    641                 }
    642 
    643                 if ( preg_match_all( '/<link [^>]+>/', $source_content, $matches ) ) {
    644                         $items = $this->_limit_array( $matches[0] );
    645 
    646                         foreach ( $items as $value ) {
    647                                 if ( preg_match( '/rel=["\'](canonical|shortlink|icon)["\']/i', $value, $matches_rel ) && preg_match( '/href=[\'"]([^\'" ]+)[\'"]/i', $value, $matches_url ) ) {
    648                                         $rel = $matches_rel[1];
    649                                         $url = $this->_limit_url( $matches_url[1] );
    650 
    651                                         if ( ! empty( $url ) && empty( $data['_links'][ $rel ] ) ) {
    652                                                 $data['_links'][ $rel ] = $url;
    653                                         }
    654                                 }
    655                         }
    656                 }
    657 
    658                 return $data;
    659         }
    660 
    661         /**
    662          * Handles backward-compat with the legacy version of Press This by supporting its query string params.
    663          *
    664          * @since 4.2.0
    665          *
    666          * @return array
    667          */
    668         public function merge_or_fetch_data() {
    669                 // Get data from $_POST and $_GET, as appropriate ($_POST > $_GET), to remain backward compatible.
    670                 $data = array();
    671 
    672                 // Only instantiate the keys we want. Sanity check and sanitize each one.
    673                 foreach ( array( 'u', 's', 't', 'v' ) as $key ) {
    674                         if ( ! empty( $_POST[ $key ] ) ) {
    675                                 $value = wp_unslash( $_POST[ $key ] );
    676                         } else if ( ! empty( $_GET[ $key ] ) ) {
    677                                 $value = wp_unslash( $_GET[ $key ] );
    678                         } else {
    679                                 continue;
    680                         }
    681 
    682                         if ( 'u' === $key ) {
    683                                 $value = $this->_limit_url( $value );
    684 
    685                                 if ( preg_match( '%^(?:https?:)?//[^/]+%i', $value, $domain_match ) ) {
    686                                         $this->domain = $domain_match[0];
    687                                 }
    688                         } else {
    689                                 $value = $this->_limit_string( $value );
    690                         }
    691 
    692                         if ( ! empty( $value ) ) {
    693                                 $data[ $key ] = $value;
    694                         }
    695                 }
    696 
    697                 /**
    698                  * Filters whether to enable in-source media discovery in Press This.
    699                  *
    700                  * @since 4.2.0
    701                  *
    702                  * @param bool $enable Whether to enable media discovery.
    703                  */
    704                 if ( apply_filters( 'enable_press_this_media_discovery', true ) ) {
    705                         /*
    706                          * If no title, _images, _embed, and _meta was passed via $_POST, fetch data from source as fallback,
    707                          * making PT fully backward compatible with the older bookmarklet.
    708                          */
    709                         if ( empty( $_POST ) && ! empty( $data['u'] ) ) {
    710                                 if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'scan-site' ) ) {
    711                                         $data = $this->source_data_fetch_fallback( $data['u'], $data );
    712                                 } else {
    713                                         $data['errors'] = 'missing nonce';
    714                                 }
    715                         } else {
    716                                 foreach ( array( '_images', '_embeds' ) as $type ) {
    717                                         if ( empty( $_POST[ $type ] ) ) {
    718                                                 continue;
    719                                         }
    720 
    721                                         $data[ $type ] = array();
    722                                         $items = $this->_limit_array( $_POST[ $type ] );
    723 
    724                                         foreach ( $items as $key => $value ) {
    725                                                 if ( $type === '_images' ) {
    726                                                         $value = $this->_limit_img( wp_unslash( $value ) );
    727                                                 } else {
    728                                                         $value = $this->_limit_embed( wp_unslash( $value ) );
    729                                                 }
    730 
    731                                                 if ( ! empty( $value ) ) {
    732                                                         $data[ $type ][] = $value;
    733                                                 }
    734                                         }
    735                                 }
    736 
    737                                 foreach ( array( '_meta', '_links' ) as $type ) {
    738                                         if ( empty( $_POST[ $type ] ) ) {
    739                                                 continue;
    740                                         }
    741 
    742                                         $data[ $type ] = array();
    743                                         $items = $this->_limit_array( $_POST[ $type ] );
    744 
    745                                         foreach ( $items as $key => $value ) {
    746                                                 // Sanity check. These are associative arrays, $key is usually things like 'title', 'description', 'keywords', etc.
    747                                                 if ( empty( $key ) || strlen( $key ) > 100 ) {
    748                                                         continue;
    749                                                 }
    750 
    751                                                 if ( $type === '_meta' ) {
    752                                                         $value = $this->_limit_string( wp_unslash( $value ) );
    753 
    754                                                         if ( ! empty( $value ) ) {
    755                                                                 $data = $this->_process_meta_entry( $key, $value, $data );
    756                                                         }
    757                                                 } else {
    758                                                         if ( in_array( $key, array( 'canonical', 'shortlink', 'icon' ), true ) ) {
    759                                                                 $data[ $type ][ $key ] = $this->_limit_url( wp_unslash( $value ) );
    760                                                         }
    761                                                 }
    762                                         }
    763                                 }
    764                         }
    765 
    766                         // Support passing a single image src as `i`
    767                         if ( ! empty( $_REQUEST['i'] ) && ( $img_src = $this->_limit_img( wp_unslash( $_REQUEST['i'] ) ) ) ) {
    768                                 if ( empty( $data['_images'] ) ) {
    769                                         $data['_images'] = array( $img_src );
    770                                 } elseif ( ! in_array( $img_src, $data['_images'], true ) ) {
    771                                         array_unshift( $data['_images'], $img_src );
    772                                 }
    773                         }
    774                 }
    775 
    776                 /**
    777                  * Filters the Press This data array.
    778                  *
    779                  * @since 4.2.0
    780                  *
    781                  * @param array $data Press This Data array.
    782                  */
    783                 return apply_filters( 'press_this_data', $data );
    784         }
    785 
    786         /**
    787          * Adds another stylesheet inside TinyMCE.
    788          *
    789          * @since 4.2.0
    790          *
    791          * @param string $styles URL to editor stylesheet.
    792          * @return string Possibly modified stylesheets list.
    793          */
    794         public function add_editor_style( $styles ) {
    795                 if ( ! empty( $styles ) ) {
    796                         $styles .= ',';
    797                 }
    798 
    799                 $press_this = admin_url( 'css/press-this-editor.css' );
    800                 if ( is_rtl() ) {
    801                         $press_this = str_replace( '.css', '-rtl.css', $press_this );
    802                 }
    803 
    804                 return $styles . $press_this;
    805         }
    806 
    807         /**
    808          * Outputs the post format selection HTML.
    809          *
    810          * @since 4.2.0
    811          *
    812          * @param WP_Post $post Post object.
    813          */
    814         public function post_formats_html( $post ) {
    815                 if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) ) {
    816                         $post_formats = get_theme_support( 'post-formats' );
    817 
    818                         if ( is_array( $post_formats[0] ) ) {
    819                                 $post_format = get_post_format( $post->ID );
    820 
    821                                 if ( ! $post_format ) {
    822                                         $post_format = '0';
    823                                 }
    824 
    825                                 // Add in the current one if it isn't there yet, in case the current theme doesn't support it.
    826                                 if ( $post_format && ! in_array( $post_format, $post_formats[0] ) ) {
    827                                         $post_formats[0][] = $post_format;
    828                                 }
    829 
    830                                 ?>
    831                                 <div id="post-formats-select">
    832                                 <fieldset><legend class="screen-reader-text"><?php _e( 'Post Formats' ); ?></legend>
    833                                         <input type="radio" name="post_format" class="post-format" id="post-format-0" value="0" <?php checked( $post_format, '0' ); ?> />
    834                                         <label for="post-format-0" class="post-format-icon post-format-standard"><?php echo get_post_format_string( 'standard' ); ?></label>
    835                                         <?php
    836 
    837                                         foreach ( $post_formats[0] as $format ) {
    838                                                 $attr_format = esc_attr( $format );
    839                                                 ?>
    840                                                 <br />
    841                                                 <input type="radio" name="post_format" class="post-format" id="post-format-<?php echo $attr_format; ?>" value="<?php echo $attr_format; ?>" <?php checked( $post_format, $format ); ?> />
    842                                                 <label for="post-format-<?php echo $attr_format ?>" class="post-format-icon post-format-<?php echo $attr_format; ?>"><?php echo esc_html( get_post_format_string( $format ) ); ?></label>
    843                                                 <?php
    844                                          }
    845 
    846                                          ?>
    847                                 </fieldset>
    848                                 </div>
    849                                 <?php
    850                         }
    851                 }
    852         }
    853 
    854         /**
    855          * Outputs the categories HTML.
    856          *
    857          * @since 4.2.0
    858          *
    859          * @param WP_Post $post Post object.
    860          */
    861         public function categories_html( $post ) {
    862                 $taxonomy = get_taxonomy( 'category' );
    863 
    864                 // Bail if user cannot assign terms
    865                 if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) {
    866                         return;
    867                 }
    868 
    869                 // Only show "add" if user can edit terms
    870                 if ( current_user_can( $taxonomy->cap->edit_terms ) ) {
    871                         ?>
    872                         <button type="button" class="add-cat-toggle button-link" aria-expanded="false">
    873                                 <span class="dashicons dashicons-plus"></span><span class="screen-reader-text"><?php _e( 'Toggle add category' ); ?></span>
    874                         </button>
    875                         <div class="add-category is-hidden">
    876                                 <label class="screen-reader-text" for="new-category"><?php echo $taxonomy->labels->add_new_item; ?></label>
    877                                 <input type="text" id="new-category" class="add-category-name" placeholder="<?php echo esc_attr( $taxonomy->labels->new_item_name ); ?>" value="" aria-required="true">
    878                                 <label class="screen-reader-text" for="new-category-parent"><?php echo $taxonomy->labels->parent_item_colon; ?></label>
    879                                 <div class="postform-wrapper">
    880                                         <?php
    881                                         wp_dropdown_categories( array(
    882                                                 'taxonomy'         => 'category',
    883                                                 'hide_empty'       => 0,
    884                                                 'name'             => 'new-category-parent',
    885                                                 'orderby'          => 'name',
    886                                                 'hierarchical'     => 1,
    887                                                 'show_option_none' => '&mdash; ' . $taxonomy->labels->parent_item . ' &mdash;'
    888                                         ) );
    889                                         ?>
    890                                 </div>
    891                                 <button type="button" class="add-cat-submit"><?php _e( 'Add' ); ?></button>
    892                         </div>
    893                         <?php
    894 
    895                 }
    896                 ?>
    897                 <div class="categories-search-wrapper">
    898                         <input id="categories-search" type="search" class="categories-search" placeholder="<?php esc_attr_e( 'Search categories by name' ) ?>">
    899                         <label for="categories-search">
    900                                 <span class="dashicons dashicons-search"></span><span class="screen-reader-text"><?php _e( 'Search categories' ); ?></span>
    901                         </label>
    902                 </div>
    903                 <div aria-label="<?php esc_attr_e( 'Categories' ); ?>">
    904                         <ul class="categories-select">
    905                                 <?php wp_terms_checklist( $post->ID, array( 'taxonomy' => 'category', 'list_only' => true ) ); ?>
    906                         </ul>
    907                 </div>
    908                 <?php
    909         }
    910 
    911         /**
    912          * Outputs the tags HTML.
    913          *
    914          * @since 4.2.0
    915          *
    916          * @param WP_Post $post Post object.
    917          */
    918         public function tags_html( $post ) {
    919                 $taxonomy              = get_taxonomy( 'post_tag' );
    920                 $user_can_assign_terms = current_user_can( $taxonomy->cap->assign_terms );
    921                 $esc_tags              = get_terms_to_edit( $post->ID, 'post_tag' );
    922 
    923                 if ( ! $esc_tags || is_wp_error( $esc_tags ) ) {
    924                         $esc_tags = '';
    925                 }
    926 
    927                 ?>
    928                 <div class="tagsdiv" id="post_tag">
    929                         <div class="jaxtag">
    930                         <input type="hidden" name="tax_input[post_tag]" class="the-tags" value="<?php echo $esc_tags; // escaped in get_terms_to_edit() ?>">
    931                         <?php
    932 
    933                         if ( $user_can_assign_terms ) {
    934                                 ?>
    935                                 <div class="ajaxtag hide-if-no-js">
    936                                         <label class="screen-reader-text" for="new-tag-post_tag"><?php _e( 'Tags' ); ?></label>
    937                                         <p>
    938                                                 <input type="text" id="new-tag-post_tag" name="newtag[post_tag]" class="newtag form-input-tip" size="16" autocomplete="off" value="" aria-describedby="new-tag-desc" />
    939                                                 <button type="button" class="tagadd"><?php _e( 'Add' ); ?></button>
    940                                         </p>
    941                                 </div>
    942                                 <p class="howto" id="new-tag-desc">
    943                                         <?php echo $taxonomy->labels->separate_items_with_commas; ?>
    944                                 </p>
    945                                 <?php
    946                         }
    947 
    948                         ?>
    949                         </div>
    950                         <div class="tagchecklist"></div>
    951                 </div>
    952                 <?php
    953 
    954                 if ( $user_can_assign_terms ) {
    955                         ?>
    956                         <button type="button" class="button-link tagcloud-link" id="link-post_tag" aria-expanded="false"><?php echo $taxonomy->labels->choose_from_most_used; ?></button>
    957                         <?php
    958                 }
    959         }
    960 
    961         /**
    962          * Get a list of embeds with no duplicates.
    963          *
    964          * @since 4.2.0
    965          *
    966          * @param array $data The site's data.
    967          * @return array Embeds selected to be available.
    968          */
    969         public function get_embeds( $data ) {
    970                 $selected_embeds = array();
    971 
    972                 // Make sure to add the Pressed page if it's a valid oembed itself
    973                 if ( ! empty ( $data['u'] ) && $this->_limit_embed( $data['u'] ) ) {
    974                         $data['_embeds'][] = $data['u'];
    975                 }
    976 
    977                 if ( ! empty( $data['_embeds'] ) ) {
    978                         foreach ( $data['_embeds'] as $src ) {
    979                                 $prot_relative_src = preg_replace( '/^https?:/', '', $src );
    980 
    981                                 if ( in_array( $prot_relative_src, $this->embeds ) ) {
    982                                         continue;
    983                                 }
    984 
    985                                 $selected_embeds[] = $src;
    986                                 $this->embeds[] = $prot_relative_src;
    987                         }
    988                 }
    989 
    990                 return $selected_embeds;
    991         }
    992 
    993         /**
    994          * Get a list of images with no duplicates.
    995          *
    996          * @since 4.2.0
    997          *
    998          * @param array $data The site's data.
    999          * @return array
    1000          */
    1001         public function get_images( $data ) {
    1002                 $selected_images = array();
    1003 
    1004                 if ( ! empty( $data['_images'] ) ) {
    1005                         foreach ( $data['_images'] as $src ) {
    1006                                 if ( false !== strpos( $src, 'gravatar.com' ) ) {
    1007                                         $src = preg_replace( '%http://[\d]+\.gravatar\.com/%', 'https://secure.gravatar.com/', $src );
    1008                                 }
    1009 
    1010                                 $prot_relative_src = preg_replace( '/^https?:/', '', $src );
    1011 
    1012                                 if ( in_array( $prot_relative_src, $this->images ) ||
    1013                                         ( false !== strpos( $src, 'avatar' ) && count( $this->images ) > 15 ) ) {
    1014                                         // Skip: already selected or some type of avatar and we've already gathered more than 15 images.
    1015                                         continue;
    1016                                 }
    1017 
    1018                                 $selected_images[] = $src;
    1019                                 $this->images[] = $prot_relative_src;
    1020                         }
    1021                 }
    1022 
    1023                 return $selected_images;
    1024         }
    1025 
    1026         /**
    1027          * Gets the source page's canonical link, based on passed location and meta data.
    1028          *
    1029          * @since 4.2.0
    1030          *
    1031          * @param array $data The site's data.
    1032          * @return string Discovered canonical URL, or empty
    1033          */
    1034         public function get_canonical_link( $data ) {
    1035                 $link = '';
    1036 
    1037                 if ( ! empty( $data['_links']['canonical'] ) ) {
    1038                         $link = $data['_links']['canonical'];
    1039                 } elseif ( ! empty( $data['u'] ) ) {
    1040                         $link = $data['u'];
    1041                 } elseif ( ! empty( $data['_meta'] ) ) {
    1042                         if ( ! empty( $data['_meta']['twitter:url'] ) ) {
    1043                                 $link = $data['_meta']['twitter:url'];
    1044                         } else if ( ! empty( $data['_meta']['og:url'] ) ) {
    1045                                 $link = $data['_meta']['og:url'];
    1046                         }
    1047                 }
    1048 
    1049                 if ( empty( $link ) && ! empty( $data['_links']['shortlink'] ) ) {
    1050                         $link = $data['_links']['shortlink'];
    1051                 }
    1052 
    1053                 return $link;
    1054         }
    1055 
    1056         /**
    1057          * Gets the source page's site name, based on passed meta data.
    1058          *
    1059          * @since 4.2.0
    1060          *
    1061          * @param array $data The site's data.
    1062          * @return string Discovered site name, or empty
    1063          */
    1064         public function get_source_site_name( $data ) {
    1065                 $name = '';
    1066 
    1067                 if ( ! empty( $data['_meta'] ) ) {
    1068                         if ( ! empty( $data['_meta']['og:site_name'] ) ) {
    1069                                 $name = $data['_meta']['og:site_name'];
    1070                         } else if ( ! empty( $data['_meta']['application-name'] ) ) {
    1071                                 $name = $data['_meta']['application-name'];
    1072                         }
    1073                 }
    1074 
    1075                 return $name;
    1076         }
    1077 
    1078         /**
    1079          * Gets the source page's title, based on passed title and meta data.
    1080          *
    1081          * @since 4.2.0
    1082          *
    1083          * @param array $data The site's data.
    1084          * @return string Discovered page title, or empty
    1085          */
    1086         public function get_suggested_title( $data ) {
    1087                 $title = '';
    1088 
    1089                 if ( ! empty( $data['t'] ) ) {
    1090                         $title = $data['t'];
    1091                 } elseif ( ! empty( $data['_meta'] ) ) {
    1092                         if ( ! empty( $data['_meta']['twitter:title'] ) ) {
    1093                                 $title = $data['_meta']['twitter:title'];
    1094                         } else if ( ! empty( $data['_meta']['og:title'] ) ) {
    1095                                 $title = $data['_meta']['og:title'];
    1096                         } else if ( ! empty( $data['_meta']['title'] ) ) {
    1097                                 $title = $data['_meta']['title'];
    1098                         }
    1099                 }
    1100 
    1101                 return $title;
    1102         }
    1103 
    1104         /**
    1105          * Gets the source page's suggested content, based on passed data (description, selection, etc).
    1106          *
    1107          * Features a blockquoted excerpt, as well as content attribution, if any.
    1108          *
    1109          * @since 4.2.0
    1110          *
    1111          * @param array $data The site's data.
    1112          * @return string Discovered content, or empty
    1113          */
    1114         public function get_suggested_content( $data ) {
    1115                 $content = $text = '';
    1116 
    1117                 if ( ! empty( $data['s'] ) ) {
    1118                         $text = $data['s'];
    1119                 } else if ( ! empty( $data['_meta'] ) ) {
    1120                         if ( ! empty( $data['_meta']['twitter:description'] ) ) {
    1121                                 $text = $data['_meta']['twitter:description'];
    1122                         } else if ( ! empty( $data['_meta']['og:description'] ) ) {
    1123                                 $text = $data['_meta']['og:description'];
    1124                         } else if ( ! empty( $data['_meta']['description'] ) ) {
    1125                                 $text = $data['_meta']['description'];
    1126                         }
    1127 
    1128                         // If there is an ellipsis at the end, the description is very likely auto-generated. Better to ignore it.
    1129                         if ( $text && substr( $text, -3 ) === '...' ) {
    1130                                 $text = '';
    1131                         }
    1132                 }
    1133 
    1134                 $default_html = array( 'quote' => '', 'link' => '', 'embed' => '' );
    1135 
    1136                 if ( ! empty( $data['u'] ) && $this->_limit_embed( $data['u'] ) ) {
    1137                         $default_html['embed'] = '<p>[embed]' . $data['u'] . '[/embed]</p>';
    1138 
    1139                         if ( ! empty( $data['s'] ) ) {
    1140                                 // If the user has selected some text, do quote it.
    1141                                 $default_html['quote'] = '<blockquote>%1$s</blockquote>';
    1142                         }
    1143                 } else {
    1144                         $default_html['quote'] = '<blockquote>%1$s</blockquote>';
    1145                         $default_html['link'] = '<p>' . _x( 'Source:', 'Used in Press This to indicate where the content comes from.' ) .
    1146                                 ' <em><a href="%1$s">%2$s</a></em></p>';
    1147                 }
    1148 
    1149                 /**
    1150                  * Filters the default HTML tags used in the suggested content for the editor.
    1151                  *
    1152                  * The HTML strings use printf format. After filtering the content is added at the specified places with `sprintf()`.
    1153                  *
    1154                  * @since 4.2.0
    1155                  *
    1156                  * @param array $default_html Associative array with three possible keys:
    1157                  *                                - 'quote' where %1$s is replaced with the site description or the selected content.
    1158                  *                                - 'link' where %1$s is link href, %2$s is link text, usually the source page title.
    1159                  *                                - 'embed' which contains an [embed] shortcode when the source page offers embeddable content.
    1160                  * @param array $data         Associative array containing the data from the source page.
    1161                  */
    1162                 $default_html = apply_filters( 'press_this_suggested_html', $default_html, $data );
    1163 
    1164                 if ( ! empty( $default_html['embed'] ) ) {
    1165                         $content .= $default_html['embed'];
    1166                 }
    1167 
    1168                 // Wrap suggested content in the specified HTML.
    1169                 if ( ! empty( $default_html['quote'] ) && $text ) {
    1170                         $content .= sprintf( $default_html['quote'], $text );
    1171                 }
    1172 
    1173                 // Add source attribution if there is one available.
    1174                 if ( ! empty( $default_html['link'] ) ) {
    1175                         $title = $this->get_suggested_title( $data );
    1176                         $url = $this->get_canonical_link( $data );
    1177 
    1178                         if ( ! $title ) {
    1179                                 $title = $this->get_source_site_name( $data );
    1180                         }
    1181 
    1182                         if ( $url && $title ) {
    1183                                 $content .= sprintf( $default_html['link'], $url, $title );
    1184                         }
    1185                 }
    1186 
    1187                 return $content;
    1188         }
    1189 
    1190         /**
    1191          * Serves the app's base HTML, which in turns calls the load script.
    1192          *
    1193          * @since 4.2.0
    1194          *
    1195          * @global WP_Locale $wp_locale
    1196          * @global bool      $is_IE
    1197          */
    1198         public function html() {
    1199                 global $wp_locale;
    1200 
    1201                 $wp_version = get_bloginfo( 'version' );
    1202 
    1203                 // Get data, new (POST) and old (GET).
    1204                 $data = $this->merge_or_fetch_data();
    1205 
    1206                 $post_title = $this->get_suggested_title( $data );
    1207 
    1208                 $post_content = $this->get_suggested_content( $data );
    1209 
    1210                 // Get site settings array/data.
    1211                 $site_settings = $this->site_settings();
    1212 
    1213                 // Pass the images and embeds
    1214                 $images = $this->get_images( $data );
    1215                 $embeds = $this->get_embeds( $data );
    1216 
    1217                 $site_data = array(
    1218                         'v' => ! empty( $data['v'] ) ? $data['v'] : '',
    1219                         'u' => ! empty( $data['u'] ) ? $data['u'] : '',
    1220                         'hasData' => ! empty( $data ) && ! isset( $data['errors'] ),
    1221                 );
    1222 
    1223                 if ( ! empty( $images ) ) {
    1224                         $site_data['_images'] = $images;
    1225                 }
    1226 
    1227                 if ( ! empty( $embeds ) ) {
    1228                         $site_data['_embeds'] = $embeds;
    1229                 }
    1230 
    1231                 // Add press-this-editor.css and remove theme's editor-style.css, if any.
    1232                 remove_editor_styles();
    1233 
    1234                 add_filter( 'mce_css', array( $this, 'add_editor_style' ) );
    1235 
    1236                 if ( ! empty( $GLOBALS['is_IE'] ) ) {
    1237                         @header( 'X-UA-Compatible: IE=edge' );
    1238                 }
    1239 
    1240                 @header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) );
    1241 
    1242 ?>
    1243 <!DOCTYPE html>
    1244 <!--[if IE 7]>         <html class="lt-ie9 lt-ie8" <?php language_attributes(); ?>> <![endif]-->
    1245 <!--[if IE 8]>         <html class="lt-ie9" <?php language_attributes(); ?>> <![endif]-->
    1246 <!--[if gt IE 8]><!--> <html <?php language_attributes(); ?>> <!--<![endif]-->
    1247 <head>
    1248         <meta http-equiv="Content-Type" content="<?php echo esc_attr( get_bloginfo( 'html_type' ) ); ?>; charset=<?php echo esc_attr( get_option( 'blog_charset' ) ); ?>" />
    1249         <meta name="viewport" content="width=device-width">
    1250         <title><?php esc_html_e( 'Press This!' ) ?></title>
    1251 
    1252         <script>
    1253                 window.wpPressThisData   = <?php echo wp_json_encode( $site_data ); ?>;
    1254                 window.wpPressThisConfig = <?php echo wp_json_encode( $site_settings ); ?>;
    1255         </script>
    1256 
    1257         <script type="text/javascript">
    1258                 var ajaxurl = '<?php echo esc_js( admin_url( 'admin-ajax.php', 'relative' ) ); ?>',
    1259                         pagenow = 'press-this',
    1260                         typenow = 'post',
    1261                         adminpage = 'press-this-php',
    1262                         thousandsSeparator = '<?php echo addslashes( $wp_locale->number_format['thousands_sep'] ); ?>',
    1263                         decimalPoint = '<?php echo addslashes( $wp_locale->number_format['decimal_point'] ); ?>',
    1264                         isRtl = <?php echo (int) is_rtl(); ?>;
    1265         </script>
    1266 
    1267         <?php
    1268                 /*
    1269                  * $post->ID is needed for the embed shortcode so we can show oEmbed previews in the editor.
    1270                  * Maybe find a way without it.
    1271                  */
    1272                 $post = get_default_post_to_edit( 'post', true );
    1273                 $post_ID = (int) $post->ID;
    1274 
    1275                 wp_enqueue_media( array( 'post' => $post_ID ) );
    1276                 wp_enqueue_style( 'press-this' );
    1277                 wp_enqueue_script( 'press-this' );
    1278                 wp_enqueue_script( 'json2' );
    1279                 wp_enqueue_script( 'editor' );
    1280 
    1281                 $categories_tax   = get_taxonomy( 'category' );
    1282                 $show_categories  = current_user_can( $categories_tax->cap->assign_terms ) || current_user_can( $categories_tax->cap->edit_terms );
    1283 
    1284                 $tag_tax          = get_taxonomy( 'post_tag' );
    1285                 $show_tags        = current_user_can( $tag_tax->cap->assign_terms );
    1286 
    1287                 $supports_formats = false;
    1288                 $post_format      = 0;
    1289 
    1290                 if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) ) {
    1291                         $supports_formats = true;
    1292 
    1293                         if ( ! ( $post_format = get_post_format( $post_ID ) ) ) {
    1294                                 $post_format = 0;
    1295                         }
    1296                 }
    1297 
    1298                 /** This action is documented in wp-admin/admin-header.php */
    1299                 do_action( 'admin_enqueue_scripts', 'press-this.php' );
    1300 
    1301                 /** This action is documented in wp-admin/admin-header.php */
    1302                 do_action( 'admin_print_styles-press-this.php' );
    1303 
    1304                 /** This action is documented in wp-admin/admin-header.php */
    1305                 do_action( 'admin_print_styles' );
    1306 
    1307                 /** This action is documented in wp-admin/admin-header.php */
    1308                 do_action( 'admin_print_scripts-press-this.php' );
    1309 
    1310                 /** This action is documented in wp-admin/admin-header.php */
    1311                 do_action( 'admin_print_scripts' );
    1312 
    1313                 /** This action is documented in wp-admin/admin-header.php */
    1314                 do_action( 'admin_head-press-this.php' );
    1315 
    1316                 /** This action is documented in wp-admin/admin-header.php */
    1317                 do_action( 'admin_head' );
    1318         ?>
    1319 </head>
    1320 <?php
    1321 
    1322         $admin_body_class  = 'press-this';
    1323         $admin_body_class .= ( is_rtl() ) ? ' rtl' : '';
    1324         $admin_body_class .= ' branch-' . str_replace( array( '.', ',' ), '-', floatval( $wp_version ) );
    1325         $admin_body_class .= ' version-' . str_replace( '.', '-', preg_replace( '/^([.0-9]+).*/', '$1', $wp_version ) );
    1326         $admin_body_class .= ' admin-color-' . sanitize_html_class( get_user_option( 'admin_color' ), 'fresh' );
    1327         $admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_user_locale() ) ) );
    1328 
    1329         /** This filter is documented in wp-admin/admin-header.php */
    1330         $admin_body_classes = apply_filters( 'admin_body_class', '' );
    1331 
    1332 ?>
    1333 <body class="wp-admin wp-core-ui <?php echo $admin_body_classes . ' ' . $admin_body_class; ?>">
    1334         <div id="adminbar" class="adminbar">
    1335                 <h1 id="current-site" class="current-site">
    1336                         <a class="current-site-link" href="<?php echo esc_url( home_url( '/' ) ); ?>" target="_blank" rel="home">
    1337                                 <span class="dashicons dashicons-wordpress"></span>
    1338                                 <span class="current-site-name"><?php bloginfo( 'name' ); ?></span>
    1339                         </a>
    1340                 </h1>
    1341                 <button type="button" class="options button-link closed">
    1342                         <span class="dashicons dashicons-tag on-closed"></span>
    1343                         <span class="screen-reader-text on-closed"><?php _e( 'Show post options' ); ?></span>
    1344                         <span aria-hidden="true" class="on-open"><?php _e( 'Done' ); ?></span>
    1345                         <span class="screen-reader-text on-open"><?php _e( 'Hide post options' ); ?></span>
    1346                 </button>
    1347         </div>
    1348 
    1349         <div id="scanbar" class="scan">
    1350                 <form method="GET">
    1351                         <label for="url-scan" class="screen-reader-text"><?php _e( 'Scan site for content' ); ?></label>
    1352                         <input type="url" name="u" id="url-scan" class="scan-url" value="<?php echo esc_attr( $site_data['u'] ) ?>" placeholder="<?php esc_attr_e( 'Enter a URL to scan' ) ?>" />
    1353                         <input type="submit" name="url-scan-submit" id="url-scan-submit" class="scan-submit" value="<?php esc_attr_e( 'Scan' ) ?>" />
    1354                         <?php wp_nonce_field( 'scan-site' ); ?>
    1355                 </form>
    1356         </div>
    1357 
    1358         <form id="pressthis-form" method="post" action="post.php" autocomplete="off">
    1359                 <input type="hidden" name="post_ID" id="post_ID" value="<?php echo $post_ID; ?>" />
    1360                 <input type="hidden" name="action" value="press-this-save-post" />
    1361                 <input type="hidden" name="post_status" id="post_status" value="draft" />
    1362                 <input type="hidden" name="wp-preview" id="wp-preview" value="" />
    1363                 <input type="hidden" name="post_title" id="post_title" value="" />
    1364                 <input type="hidden" name="pt-force-redirect" id="pt-force-redirect" value="" />
    1365                 <?php
    1366 
    1367                 wp_nonce_field( 'update-post_' . $post_ID, '_wpnonce', false );
    1368                 wp_nonce_field( 'add-category', '_ajax_nonce-add-category', false );
    1369 
    1370                 ?>
    1371 
    1372         <div class="wrapper">
    1373                 <div class="editor-wrapper">
    1374                         <div class="alerts" role="alert" aria-live="assertive" aria-relevant="all" aria-atomic="true">
    1375                                 <?php
    1376 
    1377                                 if ( isset( $data['v'] ) && $this->version > $data['v'] ) {
    1378                                         ?>
    1379                                         <p class="alert is-notice">
    1380                                                 <?php printf( __( 'You should upgrade <a href="%s" target="_blank">your bookmarklet</a> to the latest version!' ), admin_url( 'tools.php' ) ); ?>
    1381                                         </p>
    1382                                         <?php
    1383                                 }
    1384 
    1385                                 ?>
    1386                         </div>
    1387 
    1388                         <div id="app-container" class="editor">
    1389                                 <span id="title-container-label" class="post-title-placeholder" aria-hidden="true"><?php _e( 'Post title' ); ?></span>
    1390                                 <h2 id="title-container" class="post-title" contenteditable="true" spellcheck="true" aria-label="<?php esc_attr_e( 'Post title' ); ?>" tabindex="0"><?php echo esc_html( $post_title ); ?></h2>
    1391 
    1392                                 <div class="media-list-container">
    1393                                         <div class="media-list-inner-container">
    1394                                                 <h2 class="screen-reader-text"><?php _e( 'Suggested media' ); ?></h2>
    1395                                                 <ul class="media-list"></ul>
    1396                                         </div>
    1397                                 </div>
    1398 
    1399                                 <?php
    1400                                 wp_editor( $post_content, 'pressthis', array(
    1401                                         'drag_drop_upload' => true,
    1402                                         'editor_height'    => 600,
    1403                                         'media_buttons'    => false,
    1404                                         'textarea_name'    => 'post_content',
    1405                                         'teeny'            => true,
    1406                                         'tinymce'          => array(
    1407                                                 'resize'                => false,
    1408                                                 'wordpress_adv_hidden'  => false,
    1409                                                 'add_unload_trigger'    => false,
    1410                                                 'statusbar'             => false,
    1411                                                 'autoresize_min_height' => 600,
    1412                                                 'wp_autoresize_on'      => true,
    1413                                                 'plugins'               => 'lists,media,paste,tabfocus,fullscreen,wordpress,wpautoresize,wpeditimage,wpgallery,wplink,wptextpattern,wpview',
    1414                                                 'toolbar1'              => 'bold,italic,bullist,numlist,blockquote,link,unlink',
    1415                                                 'toolbar2'              => 'undo,redo',
    1416                                         ),
    1417                                         'quicktags' => array(
    1418                                                 'buttons' => 'strong,em,link,block,del,ins,img,ul,ol,li,code,more',
    1419                                         ),
    1420                                 ) );
    1421 
    1422                                 ?>
    1423                         </div>
    1424                 </div>
    1425 
    1426                 <div class="options-panel-back is-hidden" tabindex="-1"></div>
    1427                 <div class="options-panel is-off-screen is-hidden" tabindex="-1">
    1428                         <div class="post-options">
    1429 
    1430                                 <?php if ( $supports_formats ) : ?>
    1431                                         <button type="button" class="post-option">
    1432                                                 <span class="dashicons dashicons-admin-post"></span>
    1433                                                 <span class="post-option-title"><?php _ex( 'Format', 'post format' ); ?></span>
    1434                                                 <span class="post-option-contents" id="post-option-post-format"><?php echo esc_html( get_post_format_string( $post_format ) ); ?></span>
    1435                                                 <span class="dashicons post-option-forward"></span>
    1436                                         </button>
    1437                                 <?php endif; ?>
    1438 
    1439                                 <?php if ( $show_categories ) : ?>
    1440                                         <button type="button" class="post-option">
    1441                                                 <span class="dashicons dashicons-category"></span>
    1442                                                 <span class="post-option-title"><?php _e( 'Categories' ); ?></span>
    1443                                                 <span class="dashicons post-option-forward"></span>
    1444                                         </button>
    1445                                 <?php endif; ?>
    1446 
    1447                                 <?php if ( $show_tags ) : ?>
    1448                                         <button type="button" class="post-option">
    1449                                                 <span class="dashicons dashicons-tag"></span>
    1450                                                 <span class="post-option-title"><?php _e( 'Tags' ); ?></span>
    1451                                                 <span class="dashicons post-option-forward"></span>
    1452                                         </button>
    1453                                 <?php endif; ?>
    1454                         </div>
    1455 
    1456                         <?php if ( $supports_formats ) : ?>
    1457                                 <div class="setting-modal is-off-screen is-hidden">
    1458                                         <button type="button" class="modal-close">
    1459                                                 <span class="dashicons post-option-back"></span>
    1460                                                 <span class="setting-title" aria-hidden="true"><?php _ex( 'Format', 'post format' ); ?></span>
    1461                                                 <span class="screen-reader-text"><?php _e( 'Back to post options' ) ?></span>
    1462                                         </button>
    1463                                         <?php $this->post_formats_html( $post ); ?>
    1464                                 </div>
    1465                         <?php endif; ?>
    1466 
    1467                         <?php if ( $show_categories ) : ?>
    1468                                 <div class="setting-modal is-off-screen is-hidden">
    1469                                         <button type="button" class="modal-close">
    1470                                                 <span class="dashicons post-option-back"></span>
    1471                                                 <span class="setting-title" aria-hidden="true"><?php _e( 'Categories' ); ?></span>
    1472                                                 <span class="screen-reader-text"><?php _e( 'Back to post options' ) ?></span>
    1473                                         </button>
    1474                                         <?php $this->categories_html( $post ); ?>
    1475                                 </div>
    1476                         <?php endif; ?>
    1477 
    1478                         <?php if ( $show_tags ) : ?>
    1479                                 <div class="setting-modal tags is-off-screen is-hidden">
    1480                                         <button type="button" class="modal-close">
    1481                                                 <span class="dashicons post-option-back"></span>
    1482                                                 <span class="setting-title" aria-hidden="true"><?php _e( 'Tags' ); ?></span>
    1483                                                 <span class="screen-reader-text"><?php _e( 'Back to post options' ) ?></span>
    1484                                         </button>
    1485                                         <?php $this->tags_html( $post ); ?>
    1486                                 </div>
    1487                         <?php endif; ?>
    1488                 </div><!-- .options-panel -->
    1489         </div><!-- .wrapper -->
    1490 
    1491         <div class="press-this-actions">
    1492                 <div class="pressthis-media-buttons">
    1493                         <button type="button" class="insert-media" data-editor="pressthis">
    1494                                 <span class="dashicons dashicons-admin-media"></span>
    1495                                 <span class="screen-reader-text"><?php _e( 'Add Media' ); ?></span>
    1496                         </button>
    1497                 </div>
    1498                 <div class="post-actions">
    1499                         <span class="spinner">&nbsp;</span>
    1500                         <div class="split-button">
    1501                                 <div class="split-button-head">
    1502                                         <button type="button" class="publish-button split-button-primary" aria-live="polite">
    1503                                                 <span class="publish"><?php echo ( current_user_can( 'publish_posts' ) ) ? __( 'Publish' ) : __( 'Submit for Review' ); ?></span>
    1504                                                 <span class="saving-draft"><?php _e( 'Saving&hellip;' ); ?></span>
    1505                                         </button><button type="button" class="split-button-toggle" aria-haspopup="true" aria-expanded="false">
    1506                                                 <i class="dashicons dashicons-arrow-down-alt2"></i>
    1507                                                 <span class="screen-reader-text"><?php _e('More actions'); ?></span>
    1508                                         </button>
    1509                                 </div>
    1510                                 <ul class="split-button-body">
    1511                                         <li><button type="button" class="button-link draft-button split-button-option"><?php _e( 'Save Draft' ); ?></button></li>
    1512                                         <li><button type="button" class="button-link standard-editor-button split-button-option"><?php _e( 'Standard Editor' ); ?></button></li>
    1513                                         <li><button type="button" class="button-link preview-button split-button-option"><?php _e( 'Preview' ); ?></button></li>
    1514                                 </ul>
    1515                         </div>
    1516                 </div>
    1517         </div>
    1518         </form>
    1519 
    1520         <?php
    1521         /** This action is documented in wp-admin/admin-footer.php */
    1522         do_action( 'admin_footer', '' );
    1523 
    1524         /** This action is documented in wp-admin/admin-footer.php */
    1525         do_action( 'admin_print_footer_scripts-press-this.php' );
    1526 
    1527         /** This action is documented in wp-admin/admin-footer.php */
    1528         do_action( 'admin_print_footer_scripts' );
    1529 
    1530         /** This action is documented in wp-admin/admin-footer.php */
    1531         do_action( 'admin_footer-press-this.php' );
    1532         ?>
    1533 </body>
    1534 </html>
    1535 <?php
    1536                 die();
    1537         }
    1538 }
  • src/wp-admin/includes/update-core.php

    diff --git src/wp-admin/includes/update-core.php src/wp-admin/includes/update-core.php
    index 8557179092..f635ba8cd4 100644
    $_old_files = array( 
    716716// 4.9
    717717'wp-includes/js/plupload/plupload.flash.swf',
    718718'wp-includes/js/plupload/plupload.silverlight.xap',
     719'wp-admin/css/press-this-editor.css',
     720'wp-admin/css/press-this-editor-rtl.css',
     721'wp-admin/css/press-this-editor-rtl.min.css',
     722'wp-admin/css/press-this-editor.min.css',
     723'wp-admin/css/press-this.css',
     724'wp-admin/css/press-this-rtl.css',
     725'wp-admin/css/press-this-rtl.min.css',
     726'wp-admin/css/press-this.min.css',
     727'wp-admin/includes/class-wp-press-this.php',
     728'wp-admin/js/press-this.js',
     729'wp-admin/js/press-this.min.js',
    719730);
    720731
    721732/**
    function update_core($from, $to) { 
    848859
    849860        /*
    850861         * Import $wp_version, $required_php_version, and $required_mysql_version from the new version.
    851          * DO NOT globalise any variables imported from `version-current.php` in this function. 
     862         * DO NOT globalise any variables imported from `version-current.php` in this function.
    852863         *
    853864         * BC Note: $wp_filesystem->wp_content_dir() returned unslashed pre-2.8
    854865         */
  • deleted file src/wp-admin/js/press-this.js

    diff --git src/wp-admin/js/press-this.js src/wp-admin/js/press-this.js
    deleted file mode 100644
    index 5d4d16546d..0000000000
    + -  
    1 /**
    2  * PressThis App
    3  *
    4  */
    5 ( function( $, window ) {
    6         var PressThis = function() {
    7                 var editor, $mediaList, $mediaThumbWrap,
    8                         $window               = $( window ),
    9                         $document             = $( document ),
    10                         saveAlert             = false,
    11                         sidebarIsOpen         = false,
    12                         settings              = window.wpPressThisConfig || {},
    13                         data                  = window.wpPressThisData || {},
    14                         smallestWidth         = 128,
    15                         hasSetFocus           = false,
    16                         catsCache             = [],
    17                         isOffScreen           = 'is-off-screen',
    18                         isHidden              = 'is-hidden',
    19                         offscreenHidden       = isOffScreen + ' ' + isHidden,
    20                         iOS                   = /iPad|iPod|iPhone/.test( window.navigator.userAgent ),
    21                         $textEditor           = $( '#pressthis' ),
    22                         textEditor            = $textEditor[0],
    23                         textEditorMinHeight   = 600,
    24                         textLength            = 0,
    25                         transitionEndEvent    = ( function() {
    26                                 var style = document.documentElement.style;
    27 
    28                                 if ( typeof style.transition !== 'undefined' ) {
    29                                         return 'transitionend';
    30                                 }
    31 
    32                                 if ( typeof style.WebkitTransition !== 'undefined' ) {
    33                                         return 'webkitTransitionEnd';
    34                                 }
    35 
    36                                 return false;
    37                         }() );
    38 
    39                 /* ***************************************************************
    40                  * HELPER FUNCTIONS
    41                  *************************************************************** */
    42 
    43                 /**
    44                  * Emulates our PHP __() gettext function, powered by the strings exported in pressThisL10n.
    45                  *
    46                  * @param key string Key of the string to be translated, as found in pressThisL10n.
    47                  * @returns string Original or translated string, or empty string if no key.
    48                  */
    49                 function __( key ) {
    50                         if ( key && window.pressThisL10n ) {
    51                                 return window.pressThisL10n[key] || key;
    52                         }
    53 
    54                         return key || '';
    55                 }
    56 
    57                 /**
    58                  * Allow only HTTP or protocol relative URLs.
    59                  *
    60                  * @param url string The URL.
    61                  * @returns string Processed URL.
    62                  */
    63                 function checkUrl( url ) {
    64                         url = $.trim( url || '' );
    65 
    66                         if ( /^(?:https?:)?\/\//.test( url ) ) {
    67                                 url = wp.sanitize.stripTags( url );
    68                                 return url.replace( /["\\]+/g, '' );
    69                         }
    70 
    71                         return '';
    72                 }
    73 
    74                 /**
    75                  * Show UX spinner
    76                  */
    77                 function showSpinner() {
    78                         $( '.spinner' ).addClass( 'is-active' );
    79                         $( '.post-actions button' ).attr( 'disabled', 'disabled' );
    80                 }
    81 
    82                 /**
    83                  * Hide UX spinner
    84                  */
    85                 function hideSpinner() {
    86                         $( '.spinner' ).removeClass( 'is-active' );
    87                         $( '.post-actions button' ).removeAttr( 'disabled' );
    88                 }
    89 
    90                 function textEditorResize( reset ) {
    91                         var pageYOffset, height;
    92 
    93                         if ( editor && ! editor.isHidden() ) {
    94                                 return;
    95                         }
    96 
    97                         reset = ( reset === 'reset' ) || ( textLength && textLength > textEditor.value.length );
    98                         height = textEditor.style.height;
    99 
    100                         if ( reset ) {
    101                                 pageYOffset = window.pageYOffset;
    102 
    103                                 textEditor.style.height = 'auto';
    104                                 textEditor.style.height = Math.max( textEditor.scrollHeight, textEditorMinHeight ) + 'px';
    105                                 window.scrollTo( window.pageXOffset, pageYOffset );
    106                         } else if ( parseInt( textEditor.style.height, 10 ) < textEditor.scrollHeight ) {
    107                                 textEditor.style.height = textEditor.scrollHeight + 'px';
    108                         }
    109 
    110                         textLength = textEditor.value.length;
    111                 }
    112 
    113                 function mceGetCursorOffset() {
    114                         if ( ! editor ) {
    115                                 return false;
    116                         }
    117 
    118                         var node = editor.selection.getNode(),
    119                                 range, view, offset;
    120 
    121                         if ( editor.wp && editor.wp.getView && ( view = editor.wp.getView( node ) ) ) {
    122                                 offset = view.getBoundingClientRect();
    123                         } else {
    124                                 range = editor.selection.getRng();
    125 
    126                                 try {
    127                                         offset = range.getClientRects()[0];
    128                                 } catch( er ) {}
    129 
    130                                 if ( ! offset ) {
    131                                         offset = node.getBoundingClientRect();
    132                                 }
    133                         }
    134 
    135                         return offset.height ? offset : false;
    136                 }
    137 
    138                 // Make sure the caret is always visible.
    139                 function mceKeyup( event ) {
    140                         var VK = window.tinymce.util.VK,
    141                                 key = event.keyCode;
    142 
    143                         // Bail on special keys.
    144                         if ( key <= 47 && ! ( key === VK.SPACEBAR || key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE || key === VK.UP || key === VK.LEFT || key === VK.DOWN || key === VK.UP ) ) {
    145                                 return;
    146                         // OS keys, function keys, num lock, scroll lock
    147                         } else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) {
    148                                 return;
    149                         }
    150 
    151                         mceScroll( key );
    152                 }
    153 
    154                 function mceScroll( key ) {
    155                         var cursorTop, cursorBottom, editorBottom,
    156                                 offset = mceGetCursorOffset(),
    157                                 bufferTop = 50,
    158                                 bufferBottom = 65,
    159                                 VK = window.tinymce.util.VK;
    160 
    161                         if ( ! offset ) {
    162                                 return;
    163                         }
    164 
    165                         cursorTop = offset.top + editor.iframeElement.getBoundingClientRect().top;
    166                         cursorBottom = cursorTop + offset.height;
    167                         cursorTop = cursorTop - bufferTop;
    168                         cursorBottom = cursorBottom + bufferBottom;
    169                         editorBottom = $window.height();
    170 
    171                         // Don't scroll if the node is taller than the visible part of the editor
    172                         if ( editorBottom < offset.height ) {
    173                                 return;
    174                         }
    175 
    176                         if ( cursorTop < 0 && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) {
    177                                 window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset );
    178                         } else if ( cursorBottom > editorBottom ) {
    179                                 window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom );
    180                         }
    181                 }
    182 
    183                 /**
    184                  * Replace emoji images with chars and sanitize the text content.
    185                  */
    186                 function getTitleText() {
    187                         var $element = $( '#title-container' );
    188 
    189                         $element.find( 'img.emoji' ).each( function() {
    190                                 var $image = $( this );
    191                                 $image.replaceWith( $( '<span>' ).text( $image.attr( 'alt' ) ) );
    192                         });
    193 
    194                         return wp.sanitize.sanitizeText( $element.text() );
    195                 }
    196 
    197                 /**
    198                  * Prepare the form data for saving.
    199                  */
    200                 function prepareFormData() {
    201                         var $form = $( '#pressthis-form' ),
    202                                 $input = $( '<input type="hidden" name="post_category[]" value="">' );
    203 
    204                         editor && editor.save();
    205 
    206                         $( '#post_title' ).val( getTitleText() );
    207 
    208                         // Make sure to flush out the tags with tagBox before saving
    209                         if ( window.tagBox ) {
    210                                 $( 'div.tagsdiv' ).each( function() {
    211                                         window.tagBox.flushTags( this, false, 1 );
    212                                 } );
    213                         }
    214 
    215                         // Get selected categories
    216                         $( '.categories-select .category' ).each( function( i, element ) {
    217                                 var $cat = $( element );
    218 
    219                                 if ( $cat.hasClass( 'selected' ) ) {
    220                                         // Have to append a node as we submit the actual form on preview
    221                                         $form.append( $input.clone().val( $cat.attr( 'data-term-id' ) || '' ) );
    222                                 }
    223                         });
    224                 }
    225 
    226                 /**
    227                  * Submit the post form via AJAX, and redirect to the proper screen if published vs saved as a draft.
    228                  *
    229                  * @param action string publish|draft
    230                  */
    231                 function submitPost( action ) {
    232                         var data;
    233 
    234                         saveAlert = false;
    235                         showSpinner();
    236 
    237                         if ( 'publish' === action ) {
    238                                 $( '#post_status' ).val( 'publish' );
    239                         }
    240 
    241                         prepareFormData();
    242                         data = $( '#pressthis-form' ).serialize();
    243 
    244                         $.ajax( {
    245                                 type: 'post',
    246                                 url: window.ajaxurl,
    247                                 data: data
    248                         }).always( function() {
    249                                 hideSpinner();
    250                                 clearNotices();
    251                                 $( '.publish-button' ).removeClass( 'is-saving' );
    252                         }).done( function( response ) {
    253                                 if ( ! response.success ) {
    254                                         renderError( response.data.errorMessage );
    255                                 } else if ( response.data.redirect ) {
    256                                         if ( window.opener && ( settings.redirInParent || response.data.force ) ) {
    257                                                 try {
    258                                                         window.opener.location.href = response.data.redirect;
    259 
    260                                                         window.setTimeout( function() {
    261                                                                 window.self.close();
    262                                                         }, 200 );
    263                                                 } catch( er ) {
    264                                                         window.location.href = response.data.redirect;
    265                                                 }
    266                                         } else {
    267                                                 window.location.href = response.data.redirect;
    268                                         }
    269                                 }
    270                         }).fail( function() {
    271                                 renderError( __( 'serverError' ) );
    272                         });
    273                 }
    274 
    275                 /**
    276                  * Inserts the media a user has selected from the presented list inside the editor, as an image or embed, based on type
    277                  *
    278                  * @param type string img|embed
    279                  * @param src string Source URL
    280                  * @param link string Optional destination link, for images (defaults to src)
    281                  */
    282                 function insertSelectedMedia( $element ) {
    283                         var src, link, newContent = '';
    284 
    285                         src = checkUrl( $element.attr( 'data-wp-src' ) || '' );
    286                         link = checkUrl( data.u );
    287 
    288                         if ( $element.hasClass( 'is-image' ) ) {
    289                                 if ( ! link ) {
    290                                         link = src;
    291                                 }
    292 
    293                                 newContent = '<a href="' + link + '"><img class="alignnone size-full" src="' + src + '" alt="" /></a>';
    294                         } else {
    295                                 newContent = '[embed]' + src + '[/embed]';
    296                         }
    297 
    298                         if ( editor && ! editor.isHidden() ) {
    299                                 if ( ! hasSetFocus ) {
    300                                         editor.setContent( '<p>' + newContent + '</p>' + editor.getContent() );
    301                                 } else {
    302                                         editor.execCommand( 'mceInsertContent', false, newContent );
    303                                 }
    304                         } else if ( window.QTags ) {
    305                                 window.QTags.insertContent( newContent );
    306                         }
    307                 }
    308 
    309                 /**
    310                  * Save a new user-generated category via AJAX
    311                  */
    312                 function saveNewCategory() {
    313                         var data,
    314                                 name = $( '#new-category' ).val();
    315 
    316                         if ( ! name ) {
    317                                 return;
    318                         }
    319 
    320                         data = {
    321                                 action: 'press-this-add-category',
    322                                 post_id: $( '#post_ID' ).val() || 0,
    323                                 name: name,
    324                                 new_cat_nonce: $( '#_ajax_nonce-add-category' ).val() || '',
    325                                 parent: $( '#new-category-parent' ).val() || 0
    326                         };
    327 
    328                         $.post( window.ajaxurl, data, function( response ) {
    329                                 if ( ! response.success ) {
    330                                         renderError( response.data.errorMessage );
    331                                 } else {
    332                                         var $parent, $ul,
    333                                                 $wrap = $( 'ul.categories-select' );
    334 
    335                                         $.each( response.data, function( i, newCat ) {
    336                                                 var $node = $( '<li>' ).append( $( '<div class="category selected" tabindex="0" role="checkbox" aria-checked="true">' )
    337                                                         .attr( 'data-term-id', newCat.term_id )
    338                                                         .text( newCat.name ) );
    339 
    340                                                 if ( newCat.parent ) {
    341                                                         if ( ! $ul || ! $ul.length ) {
    342                                                                 $parent = $wrap.find( 'div[data-term-id="' + newCat.parent + '"]' ).parent();
    343                                                                 $ul = $parent.find( 'ul.children:first' );
    344 
    345                                                                 if ( ! $ul.length ) {
    346                                                                         $ul = $( '<ul class="children">' ).appendTo( $parent );
    347                                                                 }
    348                                                         }
    349 
    350                                                         $ul.prepend( $node );
    351                                                 } else {
    352                                                         $wrap.prepend( $node );
    353                                                 }
    354 
    355                                                 $node.focus();
    356                                         } );
    357 
    358                                         refreshCatsCache();
    359                                 }
    360                         } );
    361                 }
    362 
    363                 /* ***************************************************************
    364                  * RENDERING FUNCTIONS
    365                  *************************************************************** */
    366 
    367                 /**
    368                  * Hide the form letting users enter a URL to be scanned, if a URL was already passed.
    369                  */
    370                 function renderToolsVisibility() {
    371                         if ( data.hasData ) {
    372                                 $( '#scanbar' ).hide();
    373                         }
    374                 }
    375 
    376                 /**
    377                  * Render error notice
    378                  *
    379                  * @param msg string Notice/error message
    380                  * @param error string error|notice CSS class for display
    381                  */
    382                 function renderNotice( msg, error ) {
    383                         var $alerts = $( '.editor-wrapper div.alerts' ),
    384                                 className = error ? 'is-error' : 'is-notice';
    385 
    386                         $alerts.append( $( '<p class="alert ' + className + '">' ).text( msg ) );
    387                 }
    388 
    389                 /**
    390                  * Render error notice
    391                  *
    392                  * @param msg string Error message
    393                  */
    394                 function renderError( msg ) {
    395                         renderNotice( msg, true );
    396                 }
    397 
    398                 function clearNotices() {
    399                         $( 'div.alerts' ).empty();
    400                 }
    401 
    402                 /**
    403                  * Render notices on page load, if any already
    404                  */
    405                 function renderStartupNotices() {
    406                         // Render errors sent in the data, if any
    407                         if ( data.errors ) {
    408                                 $.each( data.errors, function( i, msg ) {
    409                                         renderError( msg );
    410                                 } );
    411                         }
    412                 }
    413 
    414                 /**
    415                  * Add an image to the list of found images.
    416                  */
    417                 function addImg( src, displaySrc, i ) {
    418                         var $element = $mediaThumbWrap.clone().addClass( 'is-image' );
    419 
    420                         $element.attr( 'data-wp-src', src ).css( 'background-image', 'url(' + displaySrc + ')' )
    421                                 .find( 'span' ).text( __( 'suggestedImgAlt' ).replace( '%d', i + 1 ) );
    422 
    423                         $mediaList.append( $element );
    424                 }
    425 
    426                 /**
    427                  * Render the detected images and embed for selection, if any
    428                  */
    429                 function renderDetectedMedia() {
    430                         var found = 0;
    431 
    432                         $mediaList = $( 'ul.media-list' );
    433                         $mediaThumbWrap = $( '<li class="suggested-media-thumbnail" tabindex="0"><span class="screen-reader-text"></span></li>' );
    434 
    435                         if ( data._embeds ) {
    436                                 $.each( data._embeds, function ( i, src ) {
    437                                         var displaySrc = '',
    438                                                 cssClass = '',
    439                                                 $element = $mediaThumbWrap.clone().addClass( 'is-embed' );
    440 
    441                                         src = checkUrl( src );
    442 
    443                                         if ( src.indexOf( 'youtube.com/' ) > -1 ) {
    444                                                 displaySrc = 'https://i.ytimg.com/vi/' + src.replace( /.+v=([^&]+).*/, '$1' ) + '/hqdefault.jpg';
    445                                                 cssClass += ' is-video';
    446                                         } else if ( src.indexOf( 'youtu.be/' ) > -1 ) {
    447                                                 displaySrc = 'https://i.ytimg.com/vi/' + src.replace( /\/([^\/])$/, '$1' ) + '/hqdefault.jpg';
    448                                                 cssClass += ' is-video';
    449                                         } else if ( src.indexOf( 'dailymotion.com' ) > -1 ) {
    450                                                 displaySrc = src.replace( '/video/', '/thumbnail/video/' );
    451                                                 cssClass += ' is-video';
    452                                         } else if ( src.indexOf( 'soundcloud.com' ) > -1 ) {
    453                                                 cssClass += ' is-audio';
    454                                         } else if ( src.indexOf( 'twitter.com' ) > -1 ) {
    455                                                 cssClass += ' is-tweet';
    456                                         } else {
    457                                                 cssClass += ' is-video';
    458                                         }
    459 
    460                                         $element.attr( 'data-wp-src', src ).find( 'span' ).text( __( 'suggestedEmbedAlt' ).replace( '%d', i + 1 ) );
    461 
    462                                         if ( displaySrc ) {
    463                                                 $element.css( 'background-image', 'url(' + displaySrc + ')' );
    464                                         }
    465 
    466                                         $mediaList.append( $element );
    467                                         found++;
    468                                 } );
    469                         }
    470 
    471                         if ( data._images ) {
    472                                 $.each( data._images, function( i, src ) {
    473                                         var displaySrc, img = new Image();
    474 
    475                                         src = checkUrl( src );
    476                                         displaySrc = src.replace( /^(http[^\?]+)(\?.*)?$/, '$1' );
    477 
    478                                         if ( src.indexOf( 'files.wordpress.com/' ) > -1 ) {
    479                                                 displaySrc = displaySrc.replace( /\?.*$/, '' ) + '?w=' + smallestWidth;
    480                                         } else if ( src.indexOf( 'gravatar.com/' ) > -1 ) {
    481                                                 displaySrc = displaySrc.replace( /\?.*$/, '' ) + '?s=' + smallestWidth;
    482                                         } else {
    483                                                 displaySrc = src;
    484                                         }
    485 
    486                                         img.onload = function() {
    487                                                 if ( ( img.width && img.width < 256 ) ||
    488                                                         ( img.height && img.height < 128 ) ) {
    489 
    490                                                         return;
    491                                                 }
    492 
    493                                                 addImg( src, displaySrc, i );
    494                                         };
    495 
    496                                         img.src = src;
    497                                         found++;
    498                                 } );
    499                         }
    500 
    501                         if ( found ) {
    502                                 $( '.media-list-container' ).addClass( 'has-media' );
    503                         }
    504                 }
    505 
    506                 /* ***************************************************************
    507                  * MONITORING FUNCTIONS
    508                  *************************************************************** */
    509 
    510                 /**
    511                  * Interactive navigation behavior for the options modal (post format, tags, categories)
    512                  */
    513                 function monitorOptionsModal() {
    514                         var $postOptions  = $( '.post-options' ),
    515                                 $postOption   = $( '.post-option' ),
    516                                 $settingModal = $( '.setting-modal' ),
    517                                 $modalClose   = $( '.modal-close' );
    518 
    519                         $postOption.on( 'click', function() {
    520                                 var index = $( this ).index(),
    521                                         $targetSettingModal = $settingModal.eq( index );
    522 
    523                                 $postOptions.addClass( isOffScreen )
    524                                         .one( transitionEndEvent, function() {
    525                                                 $( this ).addClass( isHidden );
    526                                         } );
    527 
    528                                 $targetSettingModal.removeClass( offscreenHidden )
    529                                         .one( transitionEndEvent, function() {
    530                                                 $( this ).find( '.modal-close' ).focus();
    531                                         } );
    532                         } );
    533 
    534                         $modalClose.on( 'click', function() {
    535                                 var $targetSettingModal = $( this ).parent(),
    536                                         index = $targetSettingModal.index();
    537 
    538                                 $postOptions.removeClass( offscreenHidden );
    539                                 $targetSettingModal.addClass( isOffScreen );
    540 
    541                                 if ( transitionEndEvent ) {
    542                                         $targetSettingModal.one( transitionEndEvent, function() {
    543                                                 $( this ).addClass( isHidden );
    544                                                 $postOption.eq( index - 1 ).focus();
    545                                         } );
    546                                 } else {
    547                                         setTimeout( function() {
    548                                                 $targetSettingModal.addClass( isHidden );
    549                                                 $postOption.eq( index - 1 ).focus();
    550                                         }, 350 );
    551                                 }
    552                         } );
    553                 }
    554 
    555                 /**
    556                  * Interactive behavior for the sidebar toggle, to show the options modals
    557                  */
    558                 function openSidebar() {
    559                         sidebarIsOpen = true;
    560 
    561                         $( '.options' ).removeClass( 'closed' ).addClass( 'open' );
    562                         $( '.press-this-actions, #scanbar' ).addClass( isHidden );
    563                         $( '.options-panel-back' ).removeClass( isHidden );
    564 
    565                         $( '.options-panel' ).removeClass( offscreenHidden )
    566                                 .one( transitionEndEvent, function() {
    567                                         $( '.post-option:first' ).focus();
    568                                 } );
    569                 }
    570 
    571                 function closeSidebar() {
    572                         sidebarIsOpen = false;
    573 
    574                         $( '.options' ).removeClass( 'open' ).addClass( 'closed' );
    575                         $( '.options-panel-back' ).addClass( isHidden );
    576                         $( '.press-this-actions, #scanbar' ).removeClass( isHidden );
    577 
    578                         $( '.options-panel' ).addClass( isOffScreen )
    579                                 .one( transitionEndEvent, function() {
    580                                         $( this ).addClass( isHidden );
    581                                         // Reset to options list
    582                                         $( '.post-options' ).removeClass( offscreenHidden );
    583                                         $( '.setting-modal').addClass( offscreenHidden );
    584                                 });
    585                 }
    586 
    587                 /**
    588                  * Interactive behavior for the post title's field placeholder
    589                  */
    590                 function monitorPlaceholder() {
    591                         var $titleField = $( '#title-container' ),
    592                                 $placeholder = $( '.post-title-placeholder' );
    593 
    594                         $titleField.on( 'focus', function() {
    595                                 $placeholder.addClass( 'is-hidden' );
    596                         }).on( 'blur', function() {
    597                                 if ( ! $titleField.text() && ! $titleField.html() ) {
    598                                         $placeholder.removeClass( 'is-hidden' );
    599                                 }
    600                         }).on( 'keyup', function() {
    601                                 saveAlert = true;
    602                         }).on( 'paste', function( event ) {
    603                                 var text, range,
    604                                         clipboard = event.originalEvent.clipboardData || window.clipboardData;
    605 
    606                                 if ( clipboard ) {
    607                                         try{
    608                                                 text = clipboard.getData( 'Text' ) || clipboard.getData( 'text/plain' );
    609 
    610                                                 if ( text ) {
    611                                                         text = $.trim( text.replace( /\s+/g, ' ' ) );
    612 
    613                                                         if ( window.getSelection ) {
    614                                                                 range = window.getSelection().getRangeAt(0);
    615 
    616                                                                 if ( range ) {
    617                                                                         if ( ! range.collapsed ) {
    618                                                                                 range.deleteContents();
    619                                                                         }
    620 
    621                                                                         range.insertNode( document.createTextNode( text ) );
    622                                                                 }
    623                                                         } else if ( document.selection ) {
    624                                                                 range = document.selection.createRange();
    625 
    626                                                                 if ( range ) {
    627                                                                         range.text = text;
    628                                                                 }
    629                                                         }
    630                                                 }
    631                                         } catch ( er ) {}
    632 
    633                                         event.preventDefault();
    634                                 }
    635 
    636                                 saveAlert = true;
    637 
    638                                 setTimeout( function() {
    639                                         $titleField.text( getTitleText() );
    640                                 }, 50 );
    641                         });
    642 
    643                         if ( $titleField.text() || $titleField.html() ) {
    644                                 $placeholder.addClass('is-hidden');
    645                         }
    646                 }
    647 
    648                 function toggleCatItem( $element ) {
    649                         if ( $element.hasClass( 'selected' ) ) {
    650                                 $element.removeClass( 'selected' ).attr( 'aria-checked', 'false' );
    651                         } else {
    652                                 $element.addClass( 'selected' ).attr( 'aria-checked', 'true' );
    653                         }
    654                 }
    655 
    656                 function monitorCatList() {
    657                         $( '.categories-select' ).on( 'click.press-this keydown.press-this', function( event ) {
    658                                 var $element = $( event.target );
    659 
    660                                 if ( $element.is( 'div.category' ) ) {
    661                                         if ( event.type === 'keydown' && event.keyCode !== 32 ) {
    662                                                 return;
    663                                         }
    664 
    665                                         toggleCatItem( $element );
    666                                         event.preventDefault();
    667                                 }
    668                         });
    669                 }
    670 
    671                 function splitButtonClose() {
    672                         $( '.split-button' ).removeClass( 'is-open' );
    673                         $( '.split-button-toggle' ).attr( 'aria-expanded', 'false' );
    674                 }
    675 
    676                 /* ***************************************************************
    677                  * PROCESSING FUNCTIONS
    678                  *************************************************************** */
    679 
    680                 /**
    681                  * Calls all the rendring related functions to happen on page load
    682                  */
    683                 function render(){
    684                         // We're on!
    685                         renderToolsVisibility();
    686                         renderDetectedMedia();
    687                         renderStartupNotices();
    688 
    689                         if ( window.tagBox ) {
    690                                 window.tagBox.init();
    691                         }
    692 
    693                         // iOS doesn't fire click events on "standard" elements without this...
    694                         if ( iOS ) {
    695                                 $( document.body ).css( 'cursor', 'pointer' );
    696                         }
    697                 }
    698 
    699                 /**
    700                  * Set app events and other state monitoring related code.
    701                  */
    702                 function monitor() {
    703                         var $splitButton = $( '.split-button' );
    704 
    705                         $document.on( 'tinymce-editor-init', function( event, ed ) {
    706                                 editor = ed;
    707 
    708                                 editor.on( 'nodechange', function() {
    709                                         hasSetFocus = true;
    710                                 });
    711 
    712                                 editor.on( 'focus', function() {
    713                                         splitButtonClose();
    714                                 });
    715 
    716                                 editor.on( 'show', function() {
    717                                         setTimeout( function() {
    718                                                 editor.execCommand( 'wpAutoResize' );
    719                                         }, 300 );
    720                                 });
    721 
    722                                 editor.on( 'hide', function() {
    723                                         setTimeout( function() {
    724                                                 textEditorResize( 'reset' );
    725                                         }, 100 );
    726                                 });
    727 
    728                                 editor.on( 'keyup', mceKeyup );
    729                                 editor.on( 'undo redo', mceScroll );
    730 
    731                         }).on( 'click.press-this keypress.press-this', '.suggested-media-thumbnail', function( event ) {
    732                                 if ( event.type === 'click' || event.keyCode === 13 ) {
    733                                         insertSelectedMedia( $( this ) );
    734                                 }
    735                         }).on( 'click.press-this', function( event ) {
    736                                 if ( ! $( event.target ).closest( 'button' ).hasClass( 'split-button-toggle' ) ) {
    737                                         splitButtonClose();
    738                                 }
    739                         });
    740 
    741                         // Publish, Draft and Preview buttons
    742                         $( '.post-actions' ).on( 'click.press-this', function( event ) {
    743                                 var location,
    744                                         $target = $( event.target ),
    745                                         $button = $target.closest( 'button' );
    746 
    747                                 if ( $button.length ) {
    748                                         if ( $button.hasClass( 'draft-button' ) ) {
    749                                                 $( '.publish-button' ).addClass( 'is-saving' );
    750                                                 submitPost( 'draft' );
    751                                         } else if ( $button.hasClass( 'publish-button' ) ) {
    752                                                 $button.addClass( 'is-saving' );
    753 
    754                                                 if ( window.history.replaceState ) {
    755                                                         location = window.location.href;
    756                                                         location += ( location.indexOf( '?' ) !== -1 ) ? '&' : '?';
    757                                                         location += 'wp-press-this-reload=true';
    758 
    759                                                         window.history.replaceState( null, null, location );
    760                                                 }
    761 
    762                                                 submitPost( 'publish' );
    763                                         } else if ( $button.hasClass( 'preview-button' ) ) {
    764                                                 prepareFormData();
    765                                                 window.opener && window.opener.focus();
    766 
    767                                                 $( '#wp-preview' ).val( 'dopreview' );
    768                                                 $( '#pressthis-form' ).attr( 'target', '_blank' ).submit().attr( 'target', '' );
    769                                                 $( '#wp-preview' ).val( '' );
    770                                         } else if ( $button.hasClass( 'standard-editor-button' ) ) {
    771                                                 $( '.publish-button' ).addClass( 'is-saving' );
    772                                                 $( '#pt-force-redirect' ).val( 'true' );
    773                                                 submitPost( 'draft' );
    774                                         } else if ( $button.hasClass( 'split-button-toggle' ) ) {
    775                                                 if ( $splitButton.hasClass( 'is-open' ) ) {
    776                                                         $splitButton.removeClass( 'is-open' );
    777                                                         $button.attr( 'aria-expanded', 'false' );
    778                                                 } else {
    779                                                         $splitButton.addClass( 'is-open' );
    780                                                         $button.attr( 'aria-expanded', 'true' );
    781                                                 }
    782                                         }
    783                                 }
    784                         });
    785 
    786                         monitorOptionsModal();
    787                         monitorPlaceholder();
    788                         monitorCatList();
    789 
    790                         $( '.options' ).on( 'click.press-this', function() {
    791                                 if ( $( this ).hasClass( 'open' ) ) {
    792                                         closeSidebar();
    793                                 } else {
    794                                         openSidebar();
    795                                 }
    796                         });
    797 
    798                         // Close the sidebar when focus moves outside of it.
    799                         $( '.options-panel, .options-panel-back' ).on( 'focusout.press-this', function() {
    800                                 setTimeout( function() {
    801                                         var node = document.activeElement,
    802                                                 $node = $( node );
    803 
    804                                         if ( sidebarIsOpen && node && ! $node.hasClass( 'options-panel-back' ) &&
    805                                                 ( node.nodeName === 'BODY' ||
    806                                                         ( ! $node.closest( '.options-panel' ).length &&
    807                                                         ! $node.closest( '.options' ).length ) ) ) {
    808 
    809                                                 closeSidebar();
    810                                         }
    811                                 }, 50 );
    812                         });
    813 
    814                         $( '#post-formats-select input' ).on( 'change', function() {
    815                                 var $this = $( this );
    816 
    817                                 if ( $this.is( ':checked' ) ) {
    818                                         $( '#post-option-post-format' ).text( $( 'label[for="' + $this.attr( 'id' ) + '"]' ).text() || '' );
    819                                 }
    820                         } );
    821 
    822                         $window.on( 'beforeunload.press-this', function() {
    823                                 if ( saveAlert || ( editor && editor.isDirty() ) ) {
    824                                         return __( 'saveAlert' );
    825                                 }
    826                         } ).on( 'resize.press-this', function() {
    827                                 if ( ! editor || editor.isHidden() ) {
    828                                         textEditorResize( 'reset' );
    829                                 }
    830                         });
    831 
    832                         $( 'button.add-cat-toggle' ).on( 'click.press-this', function() {
    833                                 var $this = $( this );
    834 
    835                                 $this.toggleClass( 'is-toggled' );
    836                                 $this.attr( 'aria-expanded', 'false' === $this.attr( 'aria-expanded' ) ? 'true' : 'false' );
    837                                 $( '.setting-modal .add-category, .categories-search-wrapper' ).toggleClass( 'is-hidden' );
    838                         } );
    839 
    840                         $( 'button.add-cat-submit' ).on( 'click.press-this', saveNewCategory );
    841 
    842                         $( '.categories-search' ).on( 'keyup.press-this', function() {
    843                                 var search = $( this ).val().toLowerCase() || '';
    844 
    845                                 // Don't search when less thasn 3 extended ASCII chars
    846                                 if ( /[\x20-\xFF]+/.test( search ) && search.length < 2 ) {
    847                                         return;
    848                                 }
    849 
    850                                 $.each( catsCache, function( i, cat ) {
    851                                         cat.node.removeClass( 'is-hidden searched-parent' );
    852                                 } );
    853 
    854                                 if ( search ) {
    855                                         $.each( catsCache, function( i, cat ) {
    856                                                 if ( cat.text.indexOf( search ) === -1 ) {
    857                                                         cat.node.addClass( 'is-hidden' );
    858                                                 } else {
    859                                                         cat.parents.addClass( 'searched-parent' );
    860                                                 }
    861                                         } );
    862                                 }
    863                         } );
    864 
    865                         $textEditor.on( 'focus.press-this input.press-this propertychange.press-this', textEditorResize );
    866 
    867                         return true;
    868                 }
    869 
    870                 function refreshCatsCache() {
    871                         $( '.categories-select' ).find( 'li' ).each( function() {
    872                                 var $this = $( this );
    873 
    874                                 catsCache.push( {
    875                                         node: $this,
    876                                         parents: $this.parents( 'li' ),
    877                                         text: $this.children( '.category' ).text().toLowerCase()
    878                                 } );
    879                         } );
    880                 }
    881 
    882                 // Let's go!
    883                 $document.ready( function() {
    884                         render();
    885                         monitor();
    886                         refreshCatsCache();
    887                 });
    888 
    889                 // Expose public methods?
    890                 return {
    891                         renderNotice: renderNotice,
    892                         renderError: renderError
    893                 };
    894         };
    895 
    896         window.wp = window.wp || {};
    897         window.wp.pressThis = new PressThis();
    898 
    899 }( jQuery, window ));
  • src/wp-admin/plugins.php

    diff --git src/wp-admin/plugins.php src/wp-admin/plugins.php
    index e19f5849e9..f31af7ca1e 100644
    if ( $action ) { 
    6363
    6464                        if ( isset($_GET['from']) && 'import' == $_GET['from'] ) {
    6565                                wp_redirect( self_admin_url("import.php?import=" . str_replace('-importer', '', dirname($plugin))) ); // overrides the ?error=true one above and redirects to the Imports page, stripping the -importer suffix
     66                        } else if ( isset($_GET['from']) && 'press-this' == $_GET['from'] ) {
     67                                wp_redirect( self_admin_url( "press-this.php") );
    6668                        } else {
    6769                                wp_redirect( self_admin_url("plugins.php?activate=true&plugin_status=$status&paged=$page&s=$s") ); // overrides the ?error=true one above
    6870                        }
  • src/wp-admin/press-this.php

    diff --git src/wp-admin/press-this.php src/wp-admin/press-this.php
    index 46322bc41c..504bbd5dd3 100644
     
    66 * @subpackage Press_This
    77 */
    88
    9 define('IFRAME_REQUEST' , true);
     9define( 'IFRAME_REQUEST' , true );
     10if ( ! ( isset( $_GET['url-scan-submit'] ) && 'Scan' == $_GET['url-scan-submit'] ) ) {
     11        $_POST = $_GET = array();
     12}
    1013
    1114/** WordPress Administration Bootstrap */
    1215require_once( dirname( __FILE__ ) . '/admin.php' );
    1316
    14 if ( ! current_user_can( 'edit_posts' ) || ! current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) {
    15         wp_die(
    16                 '<h1>' . __( 'Cheatin&#8217; uh?' ) . '</h1>' .
    17                 '<p>' . __( 'Sorry, you are not allowed to create posts as this user.' ) . '</p>',
    18                 403
    19         );
     17function wp_load_press_this() {
     18        $plugin_slug  = 'press-this';
     19        $plugin_file  = 'press-this/press-this-plugin.php';
     20
     21        if ( ! current_user_can( 'edit_posts' ) || ! current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) {
     22                wp_die(
     23                        __( 'Sorry, you are not allowed to create posts as this user.' ),
     24                        __( 'Cheatin&#8217; uh?' ),
     25                        403
     26                );
     27        } elseif ( is_plugin_active( $plugin_file ) ) {
     28                include( WP_PLUGIN_DIR . '/press-this/class-wp-press-this-plugin.php' );
     29                $wp_press_this = new WP_Press_This_Plugin();
     30                $wp_press_this->html();
     31        } elseif ( current_user_can( 'activate_plugins' ) ) {
     32                if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_file ) ) {
     33                        $url = wp_nonce_url( add_query_arg( array(
     34                                'action' => 'activate',
     35                                'plugin' => $plugin_file,
     36                                'from'   => 'press-this',
     37                        ), admin_url( 'plugins.php' ) ), 'activate-plugin_' . $plugin_file );
     38                        $action = sprintf(
     39                                '<a href="%1$s" aria-label="%2$s">%2$s</a>',
     40                                esc_url( $url ),
     41                                __( 'Activate Press This' )
     42                        );
     43                } else {
     44                        if ( is_main_site() ) {
     45                                $url = wp_nonce_url( add_query_arg( array(
     46                                        'action' => 'install-plugin',
     47                                        'plugin' => $plugin_slug,
     48                                        'from'   => 'press-this',
     49                                ), self_admin_url( 'update.php' ) ), 'install-plugin_' . $plugin_slug );
     50                                $action = sprintf(
     51                                        '<a href="%1$s" class="install-now" data-slug="%2$s" data-name="%2$s" aria-label="%3$s">%3$s</a>',
     52                                        esc_url( $url ),
     53                                        esc_attr( $plugin_slug ),
     54                                        __( 'Install Now' )
     55                                );
     56                        } else {
     57                                $action = sprintf(
     58                                        /* translators: URL to wp-admin/press-this.php */
     59                                        __( 'Press This is not installed. Please install Press This from <a href="%s">the main site</a>.' ),
     60                                        get_admin_url( get_current_network_id(), 'press-this.php' )
     61                                );
     62                        }
     63                }
     64                wp_die(
     65                        __( 'The Press This plugin is required.' ) . '<br />' . $action,
     66                        __( 'Install Required' ),
     67                        200
     68                );
     69        } else {
     70                wp_die(
     71                        __( 'Press This not active. Please contact your site administrator.' ),
     72                        __( 'Install Required' ),
     73                        200
     74                );
     75        }
    2076}
    2177
    22 include( ABSPATH . 'wp-admin/includes/class-wp-press-this.php' );
    23 $wp_press_this = new WP_Press_This();
    24 $wp_press_this->html();
     78wp_load_press_this();
  • src/wp-admin/tools.php

    diff --git src/wp-admin/tools.php src/wp-admin/tools.php
    index 2110fb5e4a..b61d71f5d2 100644
    require_once( dirname( __FILE__ ) . '/admin.php' ); 
    1212$title = __('Tools');
    1313
    1414get_current_screen()->add_help_tab( array(
    15         'id'      => 'press-this',
    16         'title'   => __('Press This'),
    17         'content' => '<p>' . __('Press This is a bookmarklet that makes it easy to blog about something you come across on the web. You can use it to just grab a link, or to post an excerpt. Press This will even allow you to choose from images included on the page and use them in your post. Just drag the Press This link on this screen to your bookmarks bar in your browser, and you&#8217;ll be on your way to easier content creation. Clicking on it while on another website opens a popup window with all these options.') . '</p>',
    18 ) );
    19 get_current_screen()->add_help_tab( array(
    2015        'id'      => 'converter',
    2116        'title'   => __('Categories and Tags Converter'),
    2217        'content' => '<p>' . __('Categories have hierarchy, meaning that you can nest sub-categories. Tags do not have hierarchy and cannot be nested. Sometimes people start out using one on their posts, then later realize that the other would work better for their content.' ) . '</p>' .
    require_once( ABSPATH . 'wp-admin/admin-header.php' ); 
    3429?>
    3530<div class="wrap">
    3631<h1><?php echo esc_html( $title ); ?></h1>
    37 
    38 <?php if ( current_user_can('edit_posts') ) : ?>
    39 <div class="card pressthis">
    40         <h2><?php _e('Press This') ?></h2>
    41         <p><?php _e( 'Press This is a little tool that lets you grab bits of the web and create new posts with ease.' );?></p>
    42         <p><?php _e( 'Use Press This to clip text, images and videos from any web page. Then edit and add more straight from Press This before you save or publish it in a post on your site.' ); ?></p>
    43 
    44 
    45         <form>
    46                 <h3><?php _e( 'Install Press This' ); ?></h3>
    47                 <h4><?php _e( 'Bookmarklet' ); ?></h4>
    48                 <p><?php _e( 'Drag the bookmarklet below to your bookmarks bar. Then, when you&#8217;re on a page you want to share, simply &#8220;press&#8221; it.' ); ?></p>
    49 
    50                 <p class="pressthis-bookmarklet-wrapper">
    51                         <a class="pressthis-bookmarklet" onclick="return false;" href="<?php echo htmlspecialchars( get_shortcut_link() ); ?>"><span><?php _e( 'Press This' ); ?></span></a>
    52                         <button type="button" class="button pressthis-js-toggle js-show-pressthis-code-wrap" aria-expanded="false" aria-controls="pressthis-code-wrap">
    53                                 <span class="dashicons dashicons-clipboard"></span>
    54                                 <span class="screen-reader-text"><?php _e( 'Copy &#8220;Press This&#8221; bookmarklet code' ) ?></span>
    55                         </button>
    56                 </p>
    57 
    58                 <div class="hidden js-pressthis-code-wrap clear" id="pressthis-code-wrap">
    59                         <p id="pressthis-code-desc">
    60                                 <?php _e( 'If you can&#8217;t drag the bookmarklet to your bookmarks, copy the following code and create a new bookmark. Paste the code into the new bookmark&#8217;s URL field.' ) ?>
    61                         </p>
    62                         <p>
    63                                 <textarea class="js-pressthis-code" rows="5" cols="120" readonly="readonly" aria-labelledby="pressthis-code-desc"><?php echo htmlspecialchars( get_shortcut_link() ); ?></textarea>
    64                         </p>
    65                 </div>
    66 
    67                 <h4><?php _e( 'Direct link (best for mobile)' ); ?></h4>
    68                 <p><?php _e( 'Follow the link to open Press This. Then add it to your device&#8217;s bookmarks or home screen.' ); ?></p>
    69 
    70                 <p>
    71                         <a class="button" href="<?php echo htmlspecialchars( admin_url( 'press-this.php' ) ); ?>"><?php _e( 'Open Press This' ) ?></a>
    72                 </p>
    73                 <script>
    74                         jQuery( document ).ready( function( $ ) {
    75                                 var $showPressThisWrap = $( '.js-show-pressthis-code-wrap' );
    76                                 var $pressthisCode = $( '.js-pressthis-code' );
    77 
    78                                 $showPressThisWrap.on( 'click', function( event ) {
    79                                         var $this = $( this );
    80 
    81                                         $this.parent().next( '.js-pressthis-code-wrap' ).slideToggle( 200 );
    82                                         $this.attr( 'aria-expanded', $this.attr( 'aria-expanded' ) === 'false' ? 'true' : 'false' );
    83                                 });
    84 
    85                                 // Select Press This code when focusing (tabbing) or clicking the textarea.
    86                                 $pressthisCode.on( 'click focus', function() {
    87                                         var self = this;
    88                                         setTimeout( function() { self.select(); }, 50 );
    89                                 });
    90 
    91                         });
    92                 </script>
    93         </form>
    94 </div>
    9532<?php
    96 endif;
    97 
    9833if ( current_user_can( 'import' ) ) :
    9934$cats = get_taxonomy('category');
    10035$tags = get_taxonomy('post_tag');
  • src/wp-includes/deprecated.php

    diff --git src/wp-includes/deprecated.php src/wp-includes/deprecated.php
    index 827710c0c2..06ecd4b518 100644
    function _sort_nav_menu_items( $a, $b ) { 
    38873887        else
    38883888                return strcmp( $a->$_menu_item_sort_prop, $b->$_menu_item_sort_prop );
    38893889}
     3890
     3891/**
     3892 * Retrieves the Press This bookmarklet link.
     3893 *
     3894 * @since 2.6.0
     3895 * @deprecated 4.9.0
     3896 *
     3897 */
     3898function get_shortcut_link() {
     3899        _deprecated_function( __FUNCTION__, '4.9.0' );
     3900
     3901        $link = '';
     3902
     3903        /**
     3904         * Filters the Press This bookmarklet link.
     3905         *
     3906         * @since 2.6.0
     3907         * @deprecated 4.9.0
     3908         *
     3909         * @param string $link The Press This bookmarklet link.
     3910         */
     3911        return apply_filters( 'shortcut_link', $link );
     3912}
     3913
     3914/**
     3915* Ajax handler for saving a post from Press This.
     3916*
     3917* @since 4.2.0
     3918* @deprecated 4.9.0
     3919*/
     3920function wp_ajax_press_this_save_post() {
     3921        _deprecated_function( __FUNCTION__, '4.9.0' );
     3922        if ( is_plugin_active( 'press-this/press-this-plugin.php' ) ) {
     3923                include( WP_PLUGIN_DIR . '/press-this/class-wp-press-this-plugin.php' );
     3924                $wp_press_this = new WP_Press_This_Plugin();
     3925                $wp_press_this->save_post();
     3926        } else {
     3927                wp_send_json_error( array( 'errorMessage' => __( 'The Press This plugin is required.' ) ) );
     3928        }
     3929}
     3930
     3931/**
     3932* Ajax handler for creating new category from Press This.
     3933*
     3934* @since 4.2.0
     3935* @deprecated 4.9.0
     3936*/
     3937function wp_ajax_press_this_add_category() {
     3938        _deprecated_function( __FUNCTION__, '4.9.0' );
     3939        if ( is_plugin_active( 'press-this/press-this-plugin.php' ) ) {
     3940                include( WP_PLUGIN_DIR . '/press-this/class-wp-press-this-plugin.php' );
     3941                $wp_press_this = new WP_Press_This_Plugin();
     3942                $wp_press_this->add_category();
     3943        } else {
     3944                wp_send_json_error( array( 'errorMessage' => __( 'The Press This plugin is required.' ) ) );
     3945        }
     3946}
  • src/wp-includes/link-template.php

    diff --git src/wp-includes/link-template.php src/wp-includes/link-template.php
    index f16b8f58df..b541cf473c 100644
    function the_comments_pagination( $args = array() ) { 
    28982898}
    28992899
    29002900/**
    2901  * Retrieves the Press This bookmarklet link.
    2902  *
    2903  * @since 2.6.0
    2904  *
    2905  * @global bool          $is_IE      Whether the browser matches an Internet Explorer user agent.
    2906  */
    2907 function get_shortcut_link() {
    2908         global $is_IE;
    2909 
    2910         include_once( ABSPATH . 'wp-admin/includes/class-wp-press-this.php' );
    2911 
    2912         $link = '';
    2913 
    2914         if ( $is_IE ) {
    2915                 /*
    2916                  * Return the old/shorter bookmarklet code for MSIE 8 and lower,
    2917                  * since they only support a max length of ~2000 characters for
    2918                  * bookmark[let] URLs, which is way to small for our smarter one.
    2919                  * Do update the version number so users do not get the "upgrade your
    2920                  * bookmarklet" notice when using PT in those browsers.
    2921                  */
    2922                 $ua = $_SERVER['HTTP_USER_AGENT'];
    2923 
    2924                 if ( ! empty( $ua ) && preg_match( '/\bMSIE (\d)/', $ua, $matches ) && (int) $matches[1] <= 8 ) {
    2925                         $url = wp_json_encode( admin_url( 'press-this.php' ) );
    2926 
    2927                         $link = 'javascript:var d=document,w=window,e=w.getSelection,k=d.getSelection,x=d.selection,' .
    2928                                 's=(e?e():(k)?k():(x?x.createRange().text:0)),f=' . $url . ',l=d.location,e=encodeURIComponent,' .
    2929                                 'u=f+"?u="+e(l.href)+"&t="+e(d.title)+"&s="+e(s)+"&v=' . WP_Press_This::VERSION . '";' .
    2930                                 'a=function(){if(!w.open(u,"t","toolbar=0,resizable=1,scrollbars=1,status=1,width=600,height=700"))l.href=u;};' .
    2931                                 'if(/Firefox/.test(navigator.userAgent))setTimeout(a,0);else a();void(0)';
    2932                 }
    2933         }
    2934 
    2935         if ( empty( $link ) ) {
    2936                 $src = @file_get_contents( ABSPATH . 'wp-admin/js/bookmarklet.min.js' );
    2937 
    2938                 if ( $src ) {
    2939                         $url = wp_json_encode( admin_url( 'press-this.php' ) . '?v=' . WP_Press_This::VERSION );
    2940                         $link = 'javascript:' . str_replace( 'window.pt_url', $url, $src );
    2941                 }
    2942         }
    2943 
    2944         $link = str_replace( array( "\r", "\n", "\t" ),  '', $link );
    2945 
    2946         /**
    2947          * Filters the Press This bookmarklet link.
    2948          *
    2949          * @since 2.6.0
    2950          *
    2951          * @param string $link The Press This bookmarklet link.
    2952          */
    2953         return apply_filters( 'shortcut_link', $link );
    2954 }
    2955 
    2956 /**
    29572901 * Retrieves the URL for the current site where the front end is accessible.
    29582902 *
    29592903 * Returns the 'home' option with the appropriate protocol. The protocol will be 'https'
  • src/wp-includes/script-loader.php

    diff --git src/wp-includes/script-loader.php src/wp-includes/script-loader.php
    index 61548c59b8..db115b9fa3 100644
    function wp_default_scripts( &$scripts ) { 
    646646                        'permalinkSaved' => __( 'Permalink saved' ),
    647647                ) );
    648648
    649                 $scripts->add( 'press-this', "/wp-admin/js/press-this$suffix.js", array( 'jquery', 'tags-box', 'wp-sanitize' ), false, 1 );
    650                 did_action( 'init' ) && $scripts->localize( 'press-this', 'pressThisL10n', array(
    651                         'newPost' => __( 'Title' ),
    652                         'serverError' => __( 'Connection lost or the server is busy. Please try again later.' ),
    653                         'saveAlert' => __( 'The changes you made will be lost if you navigate away from this page.' ),
    654                         /* translators: %d: nth embed found in a post */
    655                         'suggestedEmbedAlt' => __( 'Suggested embed #%d' ),
    656                         /* translators: %d: nth image found in a post */
    657                         'suggestedImgAlt' => __( 'Suggested image #%d' ),
    658                 ) );
    659 
    660649                $scripts->add( 'editor-expand', "/wp-admin/js/editor-expand$suffix.js", array( 'jquery', 'underscore' ), false, 1 );
    661650
    662651                $scripts->add( 'link', "/wp-admin/js/link$suffix.js", array( 'wp-lists', 'postbox' ), false, 1 );
    function wp_default_styles( &$styles ) { 
    935924        $styles->add( 'customize-controls',  "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'ie', 'imgareaselect' ) );
    936925        $styles->add( 'customize-widgets',   "/wp-admin/css/customize-widgets$suffix.css", array( 'wp-admin', 'colors' ) );
    937926        $styles->add( 'customize-nav-menus', "/wp-admin/css/customize-nav-menus$suffix.css", array( 'wp-admin', 'colors' ) );
    938         $styles->add( 'press-this',          "/wp-admin/css/press-this$suffix.css", array( 'buttons' ) );
    939927
    940928        $styles->add( 'ie', "/wp-admin/css/ie$suffix.css" );
    941929        $styles->add_data( 'ie', 'conditional', 'lte IE 7' );
    function wp_default_styles( &$styles ) { 
    973961                // wp-admin
    974962                'common', 'forms', 'admin-menu', 'dashboard', 'list-tables', 'edit', 'revisions', 'media', 'themes', 'about', 'nav-menus',
    975963                'widgets', 'site-icon', 'l10n', 'install', 'wp-color-picker', 'customize-controls', 'customize-widgets', 'customize-nav-menus', 'customize-preview',
    976                 'ie', 'login', 'press-this',
     964                'ie', 'login',
    977965                // wp-includes
    978966                'buttons', 'admin-bar', 'wp-auth-check', 'editor-buttons', 'media-views', 'wp-pointer',
    979967                'wp-jquery-ui-dialog',