initial
@@ -0,0 +1,602 @@
|
||||
.afmp-nav-tabs .nav-tab-active {
|
||||
background: #ffffff !important;
|
||||
}
|
||||
|
||||
.afmp-nav-tabs .nav-tab {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.afmp-nav-tabs .nav-tab:last-child {
|
||||
border-left: none !important;
|
||||
}
|
||||
|
||||
.afm__left-side h3 .button.button-primary {
|
||||
margin-left: 30px;
|
||||
margin-top: -3px;
|
||||
padding: 0 20px;
|
||||
border-radius: 15px;
|
||||
|
||||
border: none;
|
||||
background: #ffc955;
|
||||
color: #000;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
|
||||
.afm__clearfix::after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.afm__left-side {
|
||||
float: left;
|
||||
width: calc( 100% - 343px );
|
||||
max-width: calc( 100% - 343px );
|
||||
}
|
||||
|
||||
.afm__right-side {
|
||||
position: relative;
|
||||
float: right;
|
||||
display: inline-block;
|
||||
width: 300px;
|
||||
border-radius: 18px;
|
||||
border: 2px solid #dad7ff;
|
||||
background: url( ../images/grid-lines.png ), linear-gradient(214deg, #3F6972 17.61%, #011D33 135.03%);
|
||||
}
|
||||
|
||||
.afm__container {
|
||||
padding: 50px 36px;
|
||||
}
|
||||
|
||||
.fma__header {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.afmp__title {
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
line-height: 40px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.afmp__title span {
|
||||
color: #a9e5bb;
|
||||
}
|
||||
|
||||
.fma_cta {
|
||||
padding: 0 45px;
|
||||
border-radius: 53px;
|
||||
background: #ffc867;
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.fma_cta a {
|
||||
color: #000000;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 39px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.fma_cta a:focus,
|
||||
#fma__hide-banner:focus {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.fma_cta a span img {
|
||||
width: 20px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.fma__pro-features li {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 36px;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
.fma__pro-features li img {
|
||||
margin-bottom: -4px;
|
||||
margin-right: 12px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.fma__footer {
|
||||
text-align: center;
|
||||
margin-top: 17px;
|
||||
}
|
||||
|
||||
.fma__footer a {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 26px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.fma__status-mini-max {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 50px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fma__status {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.fma__maximized {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.fma__minimized {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
#fma__minimize-maximize {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.fma__pro-popup {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: rgba(0,0,0,0.1);
|
||||
backdrop-filter: blur(1px);
|
||||
z-index: 1234;
|
||||
}
|
||||
|
||||
.fma__pro-popup-wrapper {
|
||||
width: 378px;
|
||||
height: 255px;
|
||||
border-radius: 5px;
|
||||
background: url( ../images/popup-grid-lines.png ), #fff;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fma__pro-close-button {
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
right: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fma__pro-close-button a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.fma__pro-close-button a img {
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
.fma__pro-popup-content {
|
||||
width: 230px;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
.afmp__pro-popup-desc p {
|
||||
color: #6a788b;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.fma__pro-popup-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fma__pro-popup-cta {
|
||||
padding: 10px 26px;
|
||||
background: #e17351;
|
||||
border-radius: 73px;
|
||||
}
|
||||
|
||||
.fma__pro-popup-cta a {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.fma__pro-popup-cta a:focus {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.fma__left {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.fma__right {
|
||||
display: block;
|
||||
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fma__clearfix::after {
|
||||
display: table;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
------------------------------------------------------------------------
|
||||
Adminer CSS
|
||||
------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.afm__adminer-wrapper {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.afm__sidebar {
|
||||
width: 358px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.afm__sidebar .afm__container {
|
||||
padding: 22px 26px;
|
||||
}
|
||||
|
||||
.afm__header-box {
|
||||
background-color: #eeeeee;
|
||||
border-bottom: 1px solid #000000;
|
||||
padding: 23px 12px;
|
||||
}
|
||||
|
||||
.afm__placeholder-secondary {
|
||||
background-color: #B8B8B8;
|
||||
}
|
||||
|
||||
.afm__placeholder-primary {
|
||||
background-color: #89B1FC;
|
||||
}
|
||||
|
||||
.afm__placeholder {
|
||||
border-radius: 30px;
|
||||
}
|
||||
|
||||
.afm__header-box .afm_ch1.afm__placeholder {
|
||||
width: 253px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.afm__header-box .afm_ch2.afm__placeholder {
|
||||
width: 166px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.afm__mt-15 {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.afm__header-secondary-box {
|
||||
height: 70px;
|
||||
border-bottom: 1px solid #c2c2c2;
|
||||
}
|
||||
|
||||
.afm__inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.afm__placeholder-primary-gradient {
|
||||
background: linear-gradient(90deg, #89B2FF 0%, rgba(0, 51, 146, 0.00) 100%);
|
||||
}
|
||||
|
||||
.afm__header-secondary-box .afm__placeholder {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.afm__ml-20 {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.afm__database .afm__placeholder {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.afm__m-5 {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.afm__main-content {
|
||||
width: calc(100% - 358px);
|
||||
float: right;
|
||||
}
|
||||
|
||||
.afm__adminer-wrapper::after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.afm__header {
|
||||
padding: 25px 25px;
|
||||
background-color: #ddf;
|
||||
border-bottom: 1px solid #000000;
|
||||
}
|
||||
|
||||
.mt-22 {
|
||||
margin-top: 22px;
|
||||
}
|
||||
|
||||
.afm__header .afm__placeholder {
|
||||
height: 16px;
|
||||
width: 651px;
|
||||
}
|
||||
|
||||
.afm__header .afm__placeholder-primary {
|
||||
background-color: #B6B6F1;
|
||||
}
|
||||
|
||||
.float-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.clearfix::after {
|
||||
clear: both;
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
|
||||
.fma__logout-btn {
|
||||
height: 23px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #b8b8b8;
|
||||
background-color: #eeeeee;
|
||||
padding: 4px 13px;
|
||||
margin: 0;
|
||||
|
||||
color: #7a7a7a;
|
||||
font-family: Inter;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.afm__main-content .fma__container {
|
||||
padding: 0 25px 25px 0;
|
||||
}
|
||||
|
||||
.afm__secondary-header {
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
.afm__secondary-header .afm__inline {
|
||||
display: inline-block;
|
||||
margin-left: 26px;
|
||||
}
|
||||
|
||||
.afm__secondary-header .afm__inline:last-child {
|
||||
margin-left: 35px;
|
||||
}
|
||||
|
||||
.afm__secondary-header .afm__placeholder {
|
||||
height: 16px;
|
||||
width: 124px;
|
||||
}
|
||||
|
||||
.afm__secondary-header .afm__placeholder-secondary {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
|
||||
.ml-26 {
|
||||
margin-left: 26px;
|
||||
}
|
||||
|
||||
.afm__search {
|
||||
width: 285px;
|
||||
height: 50px;
|
||||
border: 1px solid #7a7a7a;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.afm__search::after {
|
||||
position: absolute;
|
||||
top: -9px;
|
||||
left: 25px;
|
||||
width: 204px;
|
||||
height: 16px;
|
||||
border-radius: 30px;
|
||||
background-color: #c2c2c2;
|
||||
display: block;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.afm__search-field {
|
||||
border: 1px solid #c2c2c2;
|
||||
background-color: #f5f5f5;
|
||||
width: 258px;
|
||||
height: 19px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 16px;
|
||||
margin-top: 14px;
|
||||
margin-left: 9px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.afm__search-field::after {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(../images/search-icon.svg) no-repeat;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.mt-10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.afm__table-wrapper {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.afm__table-wrapper tr.afm__table-header {
|
||||
background-color: #ddf;
|
||||
}
|
||||
|
||||
.afm__table-wrapper tr.afm__table-row td {
|
||||
border: 1px solid #c2c2c2;
|
||||
height: 29px;
|
||||
}
|
||||
|
||||
.afm__checkbox {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border: 1px solid #c2c2c2;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.afm__table-row td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td:first-child .afm__placeholder {
|
||||
margin-left: 75px;
|
||||
}
|
||||
|
||||
td .afm__placeholder {
|
||||
height: 10px;
|
||||
margin-left: 19px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-1.afm__placeholder {
|
||||
width: 77px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-2.afm__placeholder {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-3.afm__placeholder {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-4.afm__placeholder {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-5.afm__placeholder {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-6.afm__placeholder {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-7.afm__placeholder {
|
||||
width: 94px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-8.afm__placeholder {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.afm__table-header td .ch-9.afm__placeholder {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
.fma__table--content .ch-1.afm__placeholder {
|
||||
width: 63%;
|
||||
}
|
||||
|
||||
.fma__table--content .ch-2.afm__placeholder {
|
||||
width: 63%;
|
||||
}
|
||||
|
||||
.fma__table--content .ch-3.afm__placeholder {
|
||||
width: 63%;
|
||||
}
|
||||
|
||||
.afm__placeholder-secondary-gradient {
|
||||
background: linear-gradient(90deg, #B8B8B8 0%, rgba(194, 194, 194, 0.68) 73.5%, rgba(221, 221, 221, 0.00) 100%);
|
||||
}
|
||||
|
||||
.afm__placeholder-primary-gradient-l {
|
||||
background: linear-gradient(90deg, rgba(0, 51, 146, 0.00) 0%, #89B2FF 100%);
|
||||
width: 63%;
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================
|
||||
File Manager File Logs
|
||||
===============================================
|
||||
*/
|
||||
.dropbox__heading,
|
||||
.filelogs__heading,
|
||||
.fma__heading {
|
||||
color: #000;
|
||||
font-size: 18px !important;
|
||||
font-style: normal;
|
||||
font-weight: 600 !important;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.filelogs__heading,
|
||||
.fma__heading {
|
||||
margin-bottom: 25px !important;
|
||||
}
|
||||
|
||||
.dropbox__heading-pro-tag,
|
||||
.filelogs__heading-pro-tag,
|
||||
.fma__heading-pro-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
background: linear-gradient(270deg, #011D33 0%, #3F6972 100%);
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.file-logs__wrap,
|
||||
.dropbox__wrap,
|
||||
.fma__wrap {
|
||||
opacity: 0.5;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.file-logs__wrap::before,
|
||||
.dropbox__wrap::before,
|
||||
.fma__wrap::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
background: transparent;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
.ui-dialog.ui-widget.ui-widget-content.ui-corner-all.ui-draggable.std42-dialog.touch-punch.elfinder-dialog.ui-resizable.elfinder-dialog-active.ui-front {
|
||||
left: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* PHP Validation Styles */
|
||||
|
||||
/* CodeMirror lint marker improvements */
|
||||
.CodeMirror-lint-marker-error {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
text-align: center;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.CodeMirror-lint-marker-error:hover {
|
||||
background-color: rgba(214, 54, 56, 0.1);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* PHP Error Dialog Styles */
|
||||
.fma-php-errors {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
.fma-php-errors h3 {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.fma-error-list {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: #f9f9f9;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.fma-error-item {
|
||||
border-radius: 4px;
|
||||
line-height: 1.4;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.fma-error-item strong {
|
||||
color: #d63638;
|
||||
}
|
||||
|
||||
.fma-btn:focus {
|
||||
box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, 0.8);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Success dialog styles */
|
||||
.fma-success-icon {
|
||||
font-size: 24px;
|
||||
color: #46b450;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Editor Toolbar Styles */
|
||||
.fma-editor-toolbar {
|
||||
background: #f1f1f1;
|
||||
border: 1px solid #ddd;
|
||||
border-bottom: none;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.fma-validate-btn {
|
||||
background: #0073aa;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 6px 12px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.fma-validate-btn:hover {
|
||||
background: #005a87;
|
||||
}
|
||||
|
||||
.fma-validate-btn:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.fma-validate-btn:focus {
|
||||
box-shadow: 0 0 0 1px #5b9dd9;
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
/**
|
||||
* FMA Enhanced Debug CSS
|
||||
*
|
||||
* Styles for enhanced debugging panel
|
||||
*
|
||||
* @package Advanced File Manager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
.fma-debug-panel {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 90%;
|
||||
max-width: 800px;
|
||||
max-height: 80vh;
|
||||
background: #fff;
|
||||
border: 1px solid #ccd0d4;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
z-index: 999999;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fma-debug-header {
|
||||
background: #f1f1f1;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid #ccd0d4;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fma-debug-header h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
color: #23282d;
|
||||
}
|
||||
|
||||
.fma-debug-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
padding: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.fma-debug-close:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.fma-debug-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.fma-debug-tabs {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #ccd0d4;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.fma-debug-tab {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 12px 20px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.fma-debug-tab:hover {
|
||||
background: #f1f1f1;
|
||||
color: #23282d;
|
||||
}
|
||||
|
||||
.fma-debug-tab.active {
|
||||
color: #0073aa;
|
||||
border-bottom-color: #0073aa;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.fma-debug-tab-content {
|
||||
display: none;
|
||||
padding: 20px;
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.fma-debug-tab-content:first-child {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.fma-debug-section h4 {
|
||||
margin: 0 0 15px 0;
|
||||
font-size: 14px;
|
||||
color: #23282d;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.fma-debug-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
background: #f9f9f9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.fma-status-indicator {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.fma-status-icon {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.fma-status-icon.fma-success {
|
||||
color: #46b450;
|
||||
}
|
||||
|
||||
.fma-status-icon.fma-error {
|
||||
color: #dc3232;
|
||||
}
|
||||
|
||||
.fma-status-text {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.fma-debug-btn {
|
||||
background: #0073aa;
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
margin-bottom: 15px;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.fma-debug-btn:hover {
|
||||
background: #005a87;
|
||||
}
|
||||
|
||||
.fma-debug-btn:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.fma-debug-results {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.fma-loading {
|
||||
padding: 10px;
|
||||
background: #f0f8ff;
|
||||
border: 1px solid #b3d9ff;
|
||||
border-radius: 4px;
|
||||
color: #0073aa;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.fma-success {
|
||||
padding: 10px;
|
||||
background: #f0f8f0;
|
||||
border: 1px solid #b3e6b3;
|
||||
border-radius: 4px;
|
||||
color: #2d5a2d;
|
||||
}
|
||||
|
||||
.fma-error {
|
||||
padding: 10px;
|
||||
background: #fff0f0;
|
||||
border: 1px solid #ffb3b3;
|
||||
border-radius: 4px;
|
||||
color: #5a2d2d;
|
||||
}
|
||||
|
||||
.fma-error-list {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.fma-error-list li {
|
||||
margin-bottom: 5px;
|
||||
color: #5a2d2d;
|
||||
}
|
||||
|
||||
.fma-error-type {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.fma-function-results {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 15px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.fma-function-item {
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.fma-function-item.working {
|
||||
border-color: #46b450;
|
||||
background: #f0f8f0;
|
||||
}
|
||||
|
||||
.fma-function-item.available {
|
||||
border-color: #ffb900;
|
||||
background: #fff8f0;
|
||||
}
|
||||
|
||||
.fma-function-item.unavailable {
|
||||
border-color: #dc3232;
|
||||
background: #fff0f0;
|
||||
}
|
||||
|
||||
.fma-function-name {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
color: #23282d;
|
||||
}
|
||||
|
||||
.fma-function-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.fma-function-status .fma-status-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.fma-function-status .fma-status-text {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.fma-function-error {
|
||||
font-size: 12px;
|
||||
color: #dc3232;
|
||||
margin-top: 5px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.fma-function-output {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-top: 5px;
|
||||
font-family: monospace;
|
||||
background: #f1f1f1;
|
||||
padding: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.fma-debug-info p {
|
||||
margin: 8px 0;
|
||||
font-size: 14px;
|
||||
color: #23282d;
|
||||
}
|
||||
|
||||
.fma-debug-info strong {
|
||||
color: #0073aa;
|
||||
}
|
||||
|
||||
.fma-debug-toggle {
|
||||
background: #ffb900;
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.fma-debug-toggle:hover {
|
||||
background: #e6a600;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 768px) {
|
||||
.fma-debug-panel {
|
||||
width: 95%;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
.fma-debug-tabs {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.fma-debug-tab {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.fma-function-results {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Animation for panel */
|
||||
.fma-debug-panel {
|
||||
animation: fma-debug-slide-in 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fma-debug-slide-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -60%);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Overlay for modal */
|
||||
.fma-debug-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999998;
|
||||
}
|
||||
|
After Width: | Height: | Size: 636 B |
|
After Width: | Height: | Size: 315 B |
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,26 @@
|
||||
<svg width="31" height="22" viewBox="0 0 31 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.53161 6.1988H2.63108V7.43963H15.3587C15.2642 7.16252 15.2494 6.86443 15.3161 6.57932C15.3827 6.29422 15.5281 6.03357 15.7357 5.82708L17.4268 4.14122C17.59 3.97626 17.788 3.84977 18.0062 3.77098C18.2245 3.69218 18.4576 3.66306 18.6886 3.68573V2.54961C18.6882 2.13314 18.5227 1.73383 18.2282 1.43934C17.9337 1.14485 17.5344 0.979267 17.1179 0.978943H2.53161C2.11541 0.980157 1.71661 1.14603 1.42232 1.44032C1.12802 1.73462 0.962152 2.13342 0.960938 2.54961V4.62813C0.962152 5.04433 1.12802 5.44313 1.42232 5.73742C1.71661 6.03172 2.11541 6.19759 2.53161 6.1988ZM7.7567 3.0627C7.89374 3.06544 8.02425 3.12181 8.12019 3.2197C8.21614 3.31759 8.26988 3.4492 8.26988 3.58627C8.26987 3.72334 8.21613 3.85495 8.12017 3.95283C8.02422 4.05071 7.89371 4.10707 7.75667 4.10981C7.61963 4.10707 7.48913 4.0507 7.39318 3.95281C7.29723 3.85492 7.24349 3.72331 7.2435 3.58624C7.2435 3.44917 7.29725 3.31757 7.3932 3.21968C7.48915 3.1218 7.61966 3.06543 7.7567 3.0627ZM5.66248 3.0627C5.79952 3.06544 5.93002 3.12181 6.02597 3.2197C6.12191 3.31759 6.17565 3.4492 6.17565 3.58627C6.17565 3.72334 6.1219 3.85495 6.02595 3.95283C5.92999 4.05071 5.79949 4.10707 5.66245 4.10981C5.5254 4.10707 5.3949 4.0507 5.29895 3.95281C5.20301 3.85492 5.14927 3.72331 5.14927 3.58624C5.14927 3.44917 5.20302 3.31757 5.29897 3.21968C5.39493 3.1218 5.52543 3.06543 5.66248 3.0627ZM3.56825 3.0627C3.70529 3.06544 3.8358 3.12181 3.93174 3.2197C4.02769 3.31759 4.08143 3.4492 4.08142 3.58627C4.08142 3.72334 4.02767 3.85495 3.93172 3.95283C3.83577 4.05071 3.70526 4.10707 3.56822 4.10981C3.43118 4.10707 3.30067 4.0507 3.20473 3.95281C3.10878 3.85492 3.05504 3.72331 3.05504 3.58624C3.05505 3.44917 3.1088 3.31757 3.20475 3.21968C3.3007 3.1218 3.43121 3.06543 3.56825 3.0627Z" fill="black"/>
|
||||
<path d="M2.53161 6.1988H2.63108V7.43963H15.3587C15.2642 7.16252 15.2494 6.86443 15.3161 6.57932C15.3827 6.29422 15.5281 6.03357 15.7357 5.82708L17.4268 4.14122C17.59 3.97626 17.788 3.84977 18.0062 3.77098C18.2245 3.69218 18.4576 3.66306 18.6886 3.68573V2.54961C18.6882 2.13314 18.5227 1.73383 18.2282 1.43934C17.9337 1.14485 17.5344 0.979267 17.1179 0.978943H2.53161C2.11541 0.980157 1.71661 1.14603 1.42232 1.44032C1.12802 1.73462 0.962152 2.13342 0.960938 2.54961V4.62813C0.962152 5.04433 1.12802 5.44313 1.42232 5.73742C1.71661 6.03172 2.11541 6.19759 2.53161 6.1988ZM7.7567 3.0627C7.89374 3.06544 8.02425 3.12181 8.12019 3.2197C8.21614 3.31759 8.26988 3.4492 8.26988 3.58627C8.26987 3.72334 8.21613 3.85495 8.12017 3.95283C8.02422 4.05071 7.89371 4.10707 7.75667 4.10981C7.61963 4.10707 7.48913 4.0507 7.39318 3.95281C7.29723 3.85492 7.24349 3.72331 7.2435 3.58624C7.2435 3.44917 7.29725 3.31757 7.3932 3.21968C7.48915 3.1218 7.61966 3.06543 7.7567 3.0627ZM5.66248 3.0627C5.79952 3.06544 5.93002 3.12181 6.02597 3.2197C6.12191 3.31759 6.17565 3.4492 6.17565 3.58627C6.17565 3.72334 6.1219 3.85495 6.02595 3.95283C5.92999 4.05071 5.79949 4.10707 5.66245 4.10981C5.5254 4.10707 5.3949 4.0507 5.29895 3.95281C5.20301 3.85492 5.14927 3.72331 5.14927 3.58624C5.14927 3.44917 5.20302 3.31757 5.29897 3.21968C5.39493 3.1218 5.52543 3.06543 5.66248 3.0627ZM3.56825 3.0627C3.70529 3.06544 3.8358 3.12181 3.93174 3.2197C4.02769 3.31759 4.08143 3.4492 4.08142 3.58627C4.08142 3.72334 4.02767 3.85495 3.93172 3.95283C3.83577 4.05071 3.70526 4.10707 3.56822 4.10981C3.43118 4.10707 3.30067 4.0507 3.20473 3.95281C3.10878 3.85492 3.05504 3.72331 3.05504 3.58624C3.05505 3.44917 3.1088 3.31757 3.20475 3.21968C3.3007 3.1218 3.43121 3.06543 3.56825 3.0627Z" fill="url(#paint0_linear_54_134)"/>
|
||||
<path d="M2.53161 6.1988H2.63108V7.43963H15.3587C15.2642 7.16252 15.2494 6.86443 15.3161 6.57932C15.3827 6.29422 15.5281 6.03357 15.7357 5.82708L17.4268 4.14122C17.59 3.97626 17.788 3.84977 18.0062 3.77098C18.2245 3.69218 18.4576 3.66306 18.6886 3.68573V2.54961C18.6882 2.13314 18.5227 1.73383 18.2282 1.43934C17.9337 1.14485 17.5344 0.979267 17.1179 0.978943H2.53161C2.11541 0.980157 1.71661 1.14603 1.42232 1.44032C1.12802 1.73462 0.962152 2.13342 0.960938 2.54961V4.62813C0.962152 5.04433 1.12802 5.44313 1.42232 5.73742C1.71661 6.03172 2.11541 6.19759 2.53161 6.1988ZM7.7567 3.0627C7.89374 3.06544 8.02425 3.12181 8.12019 3.2197C8.21614 3.31759 8.26988 3.4492 8.26988 3.58627C8.26987 3.72334 8.21613 3.85495 8.12017 3.95283C8.02422 4.05071 7.89371 4.10707 7.75667 4.10981C7.61963 4.10707 7.48913 4.0507 7.39318 3.95281C7.29723 3.85492 7.24349 3.72331 7.2435 3.58624C7.2435 3.44917 7.29725 3.31757 7.3932 3.21968C7.48915 3.1218 7.61966 3.06543 7.7567 3.0627ZM5.66248 3.0627C5.79952 3.06544 5.93002 3.12181 6.02597 3.2197C6.12191 3.31759 6.17565 3.4492 6.17565 3.58627C6.17565 3.72334 6.1219 3.85495 6.02595 3.95283C5.92999 4.05071 5.79949 4.10707 5.66245 4.10981C5.5254 4.10707 5.3949 4.0507 5.29895 3.95281C5.20301 3.85492 5.14927 3.72331 5.14927 3.58624C5.14927 3.44917 5.20302 3.31757 5.29897 3.21968C5.39493 3.1218 5.52543 3.06543 5.66248 3.0627ZM3.56825 3.0627C3.70529 3.06544 3.8358 3.12181 3.93174 3.2197C4.02769 3.31759 4.08143 3.4492 4.08142 3.58627C4.08142 3.72334 4.02767 3.85495 3.93172 3.95283C3.83577 4.05071 3.70526 4.10707 3.56822 4.10981C3.43118 4.10707 3.30067 4.0507 3.20473 3.95281C3.10878 3.85492 3.05504 3.72331 3.05504 3.58624C3.05505 3.44917 3.1088 3.31757 3.20475 3.21968C3.3007 3.1218 3.43121 3.06543 3.56825 3.0627Z" fill="#E17351"/>
|
||||
<path d="M17.4268 18.0469C17.1995 17.7804 15.5688 16.2802 15.4582 15.9893H2.53161C2.11541 15.9905 1.71662 16.1564 1.42232 16.4507C1.12803 16.745 0.962157 17.1438 0.960938 17.56V19.6385C0.962157 20.0547 1.12803 20.4535 1.42232 20.7478C1.71662 21.0421 2.11541 21.208 2.53161 21.2092H17.1179C17.5344 21.2088 17.9337 21.0433 18.2282 20.7488C18.5226 20.4543 18.6882 20.055 18.6886 19.6385V18.5024C18.4576 18.5251 18.2245 18.496 18.0062 18.4172C17.788 18.3384 17.59 18.2119 17.4268 18.0469ZM3.56825 19.1254C3.43121 19.1227 3.3007 19.0663 3.20476 18.9684C3.10881 18.8705 3.05507 18.7389 3.05508 18.6019C3.05508 18.4648 3.10883 18.3332 3.20478 18.2353C3.30073 18.1374 3.43124 18.081 3.56828 18.0783C3.70532 18.0811 3.83583 18.1374 3.93177 18.2353C4.02772 18.3332 4.08146 18.4648 4.08145 18.6019C4.08145 18.739 4.0277 18.8706 3.93175 18.9684C3.8358 19.0663 3.70529 19.1227 3.56825 19.1254ZM5.66248 19.1254C5.52543 19.1227 5.39493 19.0663 5.29898 18.9684C5.20304 18.8705 5.1493 18.7389 5.1493 18.6019C5.14931 18.4648 5.20305 18.3332 5.29901 18.2353C5.39496 18.1374 5.52546 18.081 5.66251 18.0783C5.79955 18.0811 5.93005 18.1374 6.026 18.2353C6.12195 18.3332 6.17569 18.4648 6.17568 18.6019C6.17568 18.739 6.12193 18.8706 6.02598 18.9684C5.93003 19.0663 5.79952 19.1227 5.66248 19.1254ZM7.7567 19.1254C7.61966 19.1227 7.48916 19.0663 7.39321 18.9684C7.29726 18.8705 7.24353 18.7389 7.24353 18.6019C7.24353 18.4648 7.29728 18.3332 7.39323 18.2353C7.48918 18.1374 7.61969 18.081 7.75673 18.0783C7.89378 18.0811 8.02428 18.1374 8.12023 18.2353C8.21617 18.3332 8.26991 18.4648 8.26991 18.6019C8.2699 18.739 8.21616 18.8706 8.1202 18.9684C8.02425 19.0663 7.89375 19.1227 7.7567 19.1254Z" fill="black"/>
|
||||
<path d="M17.4268 18.0469C17.1995 17.7804 15.5688 16.2802 15.4582 15.9893H2.53161C2.11541 15.9905 1.71662 16.1564 1.42232 16.4507C1.12803 16.745 0.962157 17.1438 0.960938 17.56V19.6385C0.962157 20.0547 1.12803 20.4535 1.42232 20.7478C1.71662 21.0421 2.11541 21.208 2.53161 21.2092H17.1179C17.5344 21.2088 17.9337 21.0433 18.2282 20.7488C18.5226 20.4543 18.6882 20.055 18.6886 19.6385V18.5024C18.4576 18.5251 18.2245 18.496 18.0062 18.4172C17.788 18.3384 17.59 18.2119 17.4268 18.0469ZM3.56825 19.1254C3.43121 19.1227 3.3007 19.0663 3.20476 18.9684C3.10881 18.8705 3.05507 18.7389 3.05508 18.6019C3.05508 18.4648 3.10883 18.3332 3.20478 18.2353C3.30073 18.1374 3.43124 18.081 3.56828 18.0783C3.70532 18.0811 3.83583 18.1374 3.93177 18.2353C4.02772 18.3332 4.08146 18.4648 4.08145 18.6019C4.08145 18.739 4.0277 18.8706 3.93175 18.9684C3.8358 19.0663 3.70529 19.1227 3.56825 19.1254ZM5.66248 19.1254C5.52543 19.1227 5.39493 19.0663 5.29898 18.9684C5.20304 18.8705 5.1493 18.7389 5.1493 18.6019C5.14931 18.4648 5.20305 18.3332 5.29901 18.2353C5.39496 18.1374 5.52546 18.081 5.66251 18.0783C5.79955 18.0811 5.93005 18.1374 6.026 18.2353C6.12195 18.3332 6.17569 18.4648 6.17568 18.6019C6.17568 18.739 6.12193 18.8706 6.02598 18.9684C5.93003 19.0663 5.79952 19.1227 5.66248 19.1254ZM7.7567 19.1254C7.61966 19.1227 7.48916 19.0663 7.39321 18.9684C7.29726 18.8705 7.24353 18.7389 7.24353 18.6019C7.24353 18.4648 7.29728 18.3332 7.39323 18.2353C7.48918 18.1374 7.61969 18.081 7.75673 18.0783C7.89378 18.0811 8.02428 18.1374 8.12023 18.2353C8.21617 18.3332 8.26991 18.4648 8.26991 18.6019C8.2699 18.739 8.21616 18.8706 8.1202 18.9684C8.02425 19.0663 7.89375 19.1227 7.7567 19.1254Z" fill="url(#paint1_linear_54_134)"/>
|
||||
<path d="M17.4268 18.0469C17.1995 17.7804 15.5688 16.2802 15.4582 15.9893H2.53161C2.11541 15.9905 1.71662 16.1564 1.42232 16.4507C1.12803 16.745 0.962157 17.1438 0.960938 17.56V19.6385C0.962157 20.0547 1.12803 20.4535 1.42232 20.7478C1.71662 21.0421 2.11541 21.208 2.53161 21.2092H17.1179C17.5344 21.2088 17.9337 21.0433 18.2282 20.7488C18.5226 20.4543 18.6882 20.055 18.6886 19.6385V18.5024C18.4576 18.5251 18.2245 18.496 18.0062 18.4172C17.788 18.3384 17.59 18.2119 17.4268 18.0469ZM3.56825 19.1254C3.43121 19.1227 3.3007 19.0663 3.20476 18.9684C3.10881 18.8705 3.05507 18.7389 3.05508 18.6019C3.05508 18.4648 3.10883 18.3332 3.20478 18.2353C3.30073 18.1374 3.43124 18.081 3.56828 18.0783C3.70532 18.0811 3.83583 18.1374 3.93177 18.2353C4.02772 18.3332 4.08146 18.4648 4.08145 18.6019C4.08145 18.739 4.0277 18.8706 3.93175 18.9684C3.8358 19.0663 3.70529 19.1227 3.56825 19.1254ZM5.66248 19.1254C5.52543 19.1227 5.39493 19.0663 5.29898 18.9684C5.20304 18.8705 5.1493 18.7389 5.1493 18.6019C5.14931 18.4648 5.20305 18.3332 5.29901 18.2353C5.39496 18.1374 5.52546 18.081 5.66251 18.0783C5.79955 18.0811 5.93005 18.1374 6.026 18.2353C6.12195 18.3332 6.17569 18.4648 6.17568 18.6019C6.17568 18.739 6.12193 18.8706 6.02598 18.9684C5.93003 19.0663 5.79952 19.1227 5.66248 19.1254ZM7.7567 19.1254C7.61966 19.1227 7.48916 19.0663 7.39321 18.9684C7.29726 18.8705 7.24353 18.7389 7.24353 18.6019C7.24353 18.4648 7.29728 18.3332 7.39323 18.2353C7.48918 18.1374 7.61969 18.081 7.75673 18.0783C7.89378 18.0811 8.02428 18.1374 8.12023 18.2353C8.21617 18.3332 8.26991 18.4648 8.26991 18.6019C8.2699 18.739 8.21616 18.8706 8.1202 18.9684C8.02425 19.0663 7.89375 19.1227 7.7567 19.1254Z" fill="#E17351"/>
|
||||
<path d="M2.53161 13.7014H2.63108V14.9422H15.3064C15.3597 14.6889 15.4728 14.4519 15.6362 14.2511L15.9242 13.9003L15.4635 13.8532C15.0751 13.8154 14.7149 13.6339 14.4534 13.3444C14.1919 13.0548 14.048 12.678 14.0499 12.2878V9.90036C14.0485 9.60582 14.1303 9.31687 14.2859 9.06678C14.4415 8.8167 14.6646 8.61564 14.9294 8.48676H2.53161C2.11514 8.48709 1.71583 8.65267 1.42134 8.94716C1.12685 9.24164 0.961268 9.64096 0.960938 10.0574V12.1307C0.961262 12.5472 1.12685 12.9465 1.42133 13.241C1.71582 13.5355 2.11514 13.7011 2.53161 13.7014ZM7.7567 10.5705C7.89374 10.5733 8.02425 10.6296 8.12019 10.7275C8.21614 10.8254 8.26988 10.957 8.26988 11.0941C8.26987 11.2312 8.21613 11.3628 8.12017 11.4606C8.02422 11.5585 7.89371 11.6149 7.75667 11.6176C7.61963 11.6149 7.48913 11.5585 7.39318 11.4606C7.29723 11.3627 7.24349 11.2311 7.2435 11.0941C7.2435 10.957 7.29725 10.8254 7.3932 10.7275C7.48915 10.6296 7.61966 10.5732 7.7567 10.5705ZM5.66248 10.5705C5.79952 10.5733 5.93002 10.6296 6.02597 10.7275C6.12191 10.8254 6.17565 10.957 6.17565 11.0941C6.17565 11.2312 6.1219 11.3628 6.02595 11.4606C5.92999 11.5585 5.79949 11.6149 5.66245 11.6176C5.5254 11.6149 5.3949 11.5585 5.29895 11.4606C5.20301 11.3627 5.14927 11.2311 5.14927 11.0941C5.14927 10.957 5.20302 10.8254 5.29897 10.7275C5.39493 10.6296 5.52543 10.5732 5.66248 10.5705ZM3.56825 10.5705C3.70529 10.5733 3.8358 10.6296 3.93174 10.7275C4.02769 10.8254 4.08143 10.957 4.08142 11.0941C4.08142 11.2312 4.02767 11.3628 3.93172 11.4606C3.83577 11.5585 3.70526 11.6149 3.56822 11.6176C3.43118 11.6149 3.30067 11.5585 3.20473 11.4606C3.10878 11.3627 3.05504 11.2311 3.05504 11.0941C3.05505 10.957 3.1088 10.8254 3.20475 10.7275C3.3007 10.6296 3.43121 10.5732 3.56825 10.5705Z" fill="black"/>
|
||||
<path d="M2.53161 13.7014H2.63108V14.9422H15.3064C15.3597 14.6889 15.4728 14.4519 15.6362 14.2511L15.9242 13.9003L15.4635 13.8532C15.0751 13.8154 14.7149 13.6339 14.4534 13.3444C14.1919 13.0548 14.048 12.678 14.0499 12.2878V9.90036C14.0485 9.60582 14.1303 9.31687 14.2859 9.06678C14.4415 8.8167 14.6646 8.61564 14.9294 8.48676H2.53161C2.11514 8.48709 1.71583 8.65267 1.42134 8.94716C1.12685 9.24164 0.961268 9.64096 0.960938 10.0574V12.1307C0.961262 12.5472 1.12685 12.9465 1.42133 13.241C1.71582 13.5355 2.11514 13.7011 2.53161 13.7014ZM7.7567 10.5705C7.89374 10.5733 8.02425 10.6296 8.12019 10.7275C8.21614 10.8254 8.26988 10.957 8.26988 11.0941C8.26987 11.2312 8.21613 11.3628 8.12017 11.4606C8.02422 11.5585 7.89371 11.6149 7.75667 11.6176C7.61963 11.6149 7.48913 11.5585 7.39318 11.4606C7.29723 11.3627 7.24349 11.2311 7.2435 11.0941C7.2435 10.957 7.29725 10.8254 7.3932 10.7275C7.48915 10.6296 7.61966 10.5732 7.7567 10.5705ZM5.66248 10.5705C5.79952 10.5733 5.93002 10.6296 6.02597 10.7275C6.12191 10.8254 6.17565 10.957 6.17565 11.0941C6.17565 11.2312 6.1219 11.3628 6.02595 11.4606C5.92999 11.5585 5.79949 11.6149 5.66245 11.6176C5.5254 11.6149 5.3949 11.5585 5.29895 11.4606C5.20301 11.3627 5.14927 11.2311 5.14927 11.0941C5.14927 10.957 5.20302 10.8254 5.29897 10.7275C5.39493 10.6296 5.52543 10.5732 5.66248 10.5705ZM3.56825 10.5705C3.70529 10.5733 3.8358 10.6296 3.93174 10.7275C4.02769 10.8254 4.08143 10.957 4.08142 11.0941C4.08142 11.2312 4.02767 11.3628 3.93172 11.4606C3.83577 11.5585 3.70526 11.6149 3.56822 11.6176C3.43118 11.6149 3.30067 11.5585 3.20473 11.4606C3.10878 11.3627 3.05504 11.2311 3.05504 11.0941C3.05505 10.957 3.1088 10.8254 3.20475 10.7275C3.3007 10.6296 3.43121 10.5732 3.56825 10.5705Z" fill="url(#paint2_linear_54_134)"/>
|
||||
<path d="M2.53161 13.7014H2.63108V14.9422H15.3064C15.3597 14.6889 15.4728 14.4519 15.6362 14.2511L15.9242 13.9003L15.4635 13.8532C15.0751 13.8154 14.7149 13.6339 14.4534 13.3444C14.1919 13.0548 14.048 12.678 14.0499 12.2878V9.90036C14.0485 9.60582 14.1303 9.31687 14.2859 9.06678C14.4415 8.8167 14.6646 8.61564 14.9294 8.48676H2.53161C2.11514 8.48709 1.71583 8.65267 1.42134 8.94716C1.12685 9.24164 0.961268 9.64096 0.960938 10.0574V12.1307C0.961262 12.5472 1.12685 12.9465 1.42133 13.241C1.71582 13.5355 2.11514 13.7011 2.53161 13.7014ZM7.7567 10.5705C7.89374 10.5733 8.02425 10.6296 8.12019 10.7275C8.21614 10.8254 8.26988 10.957 8.26988 11.0941C8.26987 11.2312 8.21613 11.3628 8.12017 11.4606C8.02422 11.5585 7.89371 11.6149 7.75667 11.6176C7.61963 11.6149 7.48913 11.5585 7.39318 11.4606C7.29723 11.3627 7.24349 11.2311 7.2435 11.0941C7.2435 10.957 7.29725 10.8254 7.3932 10.7275C7.48915 10.6296 7.61966 10.5732 7.7567 10.5705ZM5.66248 10.5705C5.79952 10.5733 5.93002 10.6296 6.02597 10.7275C6.12191 10.8254 6.17565 10.957 6.17565 11.0941C6.17565 11.2312 6.1219 11.3628 6.02595 11.4606C5.92999 11.5585 5.79949 11.6149 5.66245 11.6176C5.5254 11.6149 5.3949 11.5585 5.29895 11.4606C5.20301 11.3627 5.14927 11.2311 5.14927 11.0941C5.14927 10.957 5.20302 10.8254 5.29897 10.7275C5.39493 10.6296 5.52543 10.5732 5.66248 10.5705ZM3.56825 10.5705C3.70529 10.5733 3.8358 10.6296 3.93174 10.7275C4.02769 10.8254 4.08143 10.957 4.08142 11.0941C4.08142 11.2312 4.02767 11.3628 3.93172 11.4606C3.83577 11.5585 3.70526 11.6149 3.56822 11.6176C3.43118 11.6149 3.30067 11.5585 3.20473 11.4606C3.10878 11.3627 3.05504 11.2311 3.05504 11.0941C3.05505 10.957 3.1088 10.8254 3.20475 10.7275C3.3007 10.6296 3.43121 10.5732 3.56825 10.5705Z" fill="#E17351"/>
|
||||
<path d="M30.5471 9.44339L29.3896 9.32765C29.2822 9.30867 29.1812 9.26288 29.0962 9.19452C29.0111 9.12616 28.9447 9.03744 28.9031 8.93657C28.8614 8.83571 28.8459 8.72597 28.8579 8.61751C28.87 8.50906 28.9092 8.40539 28.9719 8.31612L29.7067 7.42035C29.7864 7.32431 29.8275 7.20202 29.8219 7.07734C29.8163 6.95265 29.7645 6.83453 29.6765 6.746L28.051 5.12051C27.9625 5.03253 27.8443 4.98069 27.7197 4.97511C27.595 4.96953 27.4727 5.0106 27.3767 5.09032L26.4758 5.82506C26.3865 5.88614 26.2834 5.92396 26.1757 5.93511C26.0681 5.94626 25.9594 5.93037 25.8594 5.8889C25.7595 5.84742 25.6715 5.78166 25.6034 5.69757C25.5352 5.61349 25.4892 5.51374 25.4694 5.40736L25.3536 4.24989C25.3411 4.12533 25.2826 4.00991 25.1895 3.92616C25.0965 3.84242 24.9755 3.79635 24.8504 3.79697H22.5556C22.4304 3.79635 22.3094 3.84242 22.2164 3.92616C22.1233 4.00991 22.0648 4.12533 22.0523 4.24989L21.9366 5.40736C21.9167 5.51374 21.8707 5.61348 21.8025 5.69756C21.7344 5.78164 21.6464 5.84739 21.5465 5.88886C21.4465 5.93034 21.3378 5.94622 21.2302 5.93507C21.1225 5.92392 21.0194 5.8861 20.9301 5.82502L20.0293 5.09032C19.9332 5.0106 19.8109 4.96953 19.6863 4.97511C19.5616 4.98069 19.4434 5.03253 19.3549 5.12051L17.7294 6.746C17.6415 6.83453 17.5896 6.95265 17.584 7.07734C17.5785 7.20202 17.6195 7.32431 17.6992 7.42035L18.434 8.32116C18.4952 8.41044 18.5332 8.51361 18.5444 8.62129C18.5556 8.72898 18.5398 8.83776 18.4983 8.93776C18.4568 9.03776 18.391 9.12581 18.3068 9.1939C18.2226 9.26199 18.1227 9.30796 18.0163 9.32765L16.8588 9.44339C16.7342 9.45591 16.6188 9.51441 16.5351 9.60746C16.4513 9.70052 16.4053 9.82145 16.4059 9.94664V12.2414C16.4053 12.3666 16.4513 12.4876 16.5351 12.5806C16.6188 12.6737 16.7342 12.7322 16.8588 12.7447L18.0163 12.8604C18.1231 12.8804 18.2233 12.9268 18.3077 12.9954C18.392 13.0639 18.458 13.1524 18.4995 13.2529C18.541 13.3534 18.5567 13.4626 18.5453 13.5707C18.5338 13.6789 18.4956 13.7824 18.434 13.872L17.6992 14.7677C17.6195 14.8638 17.5785 14.9861 17.584 15.1107C17.5896 15.2354 17.6415 15.3536 17.7294 15.4421L19.3549 17.0676C19.4434 17.1555 19.5616 17.2074 19.6863 17.213C19.8109 17.2185 19.9332 17.1775 20.0293 17.0978L20.9301 16.363C21.0194 16.3019 21.1226 16.2641 21.2302 16.253C21.3378 16.2418 21.4465 16.2577 21.5465 16.2992C21.6464 16.3407 21.7345 16.4064 21.8026 16.4905C21.8707 16.5746 21.9167 16.6744 21.9366 16.7807L22.0523 17.9382C22.0648 18.0628 22.1233 18.1782 22.2164 18.2619C22.3094 18.3457 22.4304 18.3918 22.5556 18.3911H24.8504C24.9755 18.3918 25.0965 18.3457 25.1895 18.2619C25.2826 18.1782 25.3411 18.0628 25.3536 17.9382L25.4694 16.7807C25.4859 16.6699 25.532 16.5656 25.6029 16.4788C25.6737 16.3921 25.7667 16.326 25.872 16.2876C25.9704 16.246 26.078 16.2311 26.184 16.2443C26.29 16.2576 26.3907 16.2985 26.4758 16.363L27.3767 17.0978C27.4727 17.1775 27.595 17.2185 27.7197 17.213C27.8443 17.2074 27.9625 17.1555 28.051 17.0676L29.6765 15.4421C29.7645 15.3536 29.8163 15.2354 29.8219 15.1107C29.8275 14.9861 29.7864 14.8638 29.7067 14.7677L28.9719 13.8669C28.9107 13.7776 28.8727 13.6745 28.8615 13.5668C28.8503 13.4591 28.8661 13.3503 28.9076 13.2503C28.9491 13.1503 29.015 13.0623 29.0992 12.9942C29.1833 12.9261 29.2832 12.8801 29.3897 12.8604L30.5471 12.7447C30.6717 12.7322 30.7871 12.6737 30.8708 12.5806C30.9546 12.4876 31.0007 12.3666 31 12.2414V9.94664C31.0007 9.82145 30.9546 9.70052 30.8708 9.60746C30.7871 9.51441 30.6717 9.45591 30.5471 9.44339ZM23.703 13.6103C20.3772 13.5066 20.378 8.68098 23.703 8.57781C27.0287 8.68148 27.028 13.5071 23.703 13.6103Z" fill="#3F6972"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_54_134" x1="-0.442319" y1="3.24119" x2="27.8062" y2="-2.48047" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9E5BB"/>
|
||||
<stop offset="1" stop-color="#3F6972"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_54_134" x1="-0.442319" y1="17.8171" x2="27.2262" y2="10.8807" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9E5BB"/>
|
||||
<stop offset="1" stop-color="#3F6972"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_54_134" x1="-0.223501" y1="10.7472" x2="23.8923" y2="6.62093" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9E5BB"/>
|
||||
<stop offset="1" stop-color="#3F6972"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg width="36" height="31" viewBox="0 0 36 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M35.5405 12.5163C34.2657 11.0991 30.4819 12.4146 27.0846 15.4593C25.2673 17.0935 23.9314 18.8905 23.2737 20.423C23.5381 20.423 23.8094 20.4365 24.0806 20.4569C25.3554 20.5518 26.3658 21.569 26.454 22.8438C26.4743 23.1354 26.4879 23.4609 26.4879 23.8067C28.0543 23.2981 29.9259 22.1861 31.6957 20.5993C35.093 17.5546 36.8154 13.9403 35.5405 12.5163Z" fill="#3F6972"/>
|
||||
<path d="M24.0128 21.3791C20.4934 21.1011 19.083 22.5387 19.083 22.5387C18.1879 23.2778 17.8149 24.3018 17.5505 25.3799C17.4013 25.9902 17.2792 26.6005 17.1165 27.204C16.9402 27.8279 16.5333 28.2076 15.862 28.2755C15.5365 28.3094 15.2992 28.4653 15.2585 28.8179C15.2178 29.1841 15.4144 29.3808 15.7399 29.5028C16.8724 29.9232 18.0726 30.1538 19.2796 30.1877C22.0327 30.2013 23.9721 29.0146 24.9621 26.7565C25.586 25.5563 25.6131 24.0102 25.5318 22.9117C25.4707 22.0979 24.8265 21.4469 24.0128 21.3791Z" fill="#3F6972"/>
|
||||
<path d="M15.6198 26.0937C15.7215 25.7275 15.8097 25.3546 15.8978 24.9613C15.9453 24.7443 15.9996 24.5205 16.047 24.3035C16.3183 23.1914 16.7455 21.9301 17.8643 20.9876C18.122 20.7502 19.2816 19.7873 21.6685 19.5907C21.7567 19.3533 21.8584 19.1024 21.9804 18.8515C22.7603 17.2173 24.1368 15.461 25.8727 13.9082C26.1779 13.6301 26.4898 13.3725 26.8085 13.1216C26.7746 12.5248 26.7068 11.9349 26.5983 11.3449C25.9338 7.77133 24.0826 4.95042 21.0921 2.90933C18.8272 1.35647 16.2979 0.644459 13.5516 0.671583C11.5512 0.691926 9.64572 1.08523 7.84197 1.92608C5.48217 3.0246 3.51566 4.59102 2.1798 6.86267C1.07449 8.70033 0.504883 10.7075 0.667628 12.8435C0.87106 15.5424 2.20692 17.6106 4.5057 19.0346C5.99074 19.9569 7.63854 20.262 9.15071 20.1874C9.80169 20.1874 10.2425 20.1942 10.6764 20.1874C10.9884 20.1806 11.2393 20.2688 11.3817 20.5604C11.5241 20.852 11.4224 21.0893 11.2325 21.3198C10.5001 22.2149 10.2492 23.2253 10.5883 24.3306C11.0494 25.8225 12.3446 26.7243 13.9449 26.6701C14.1687 26.6633 14.3925 26.6497 14.6094 26.6362C14.7858 26.5616 14.9756 26.5141 15.1655 26.4938C15.4028 26.4667 15.5317 26.4056 15.6198 26.0937ZM24.8895 12.9927C24.8895 14.5524 23.6282 15.8136 22.0686 15.8136C20.5089 15.8136 19.2477 14.5524 19.2477 12.9927C19.2477 11.4331 20.5089 10.1718 22.0686 10.1718C23.6282 10.1718 24.8895 11.4331 24.8895 12.9927ZM18.339 4.0621C19.8987 4.0621 21.1599 5.32338 21.1599 6.88301C21.1599 8.44265 19.8987 9.70393 18.339 9.70393C16.7794 9.70393 15.5181 8.44265 15.5181 6.88301C15.5181 5.32338 16.7794 4.0621 18.339 4.0621ZM5.69916 14.1862C4.13952 14.1862 2.87825 12.9249 2.87825 11.3653C2.87825 9.80564 4.13952 8.54437 5.69916 8.54437C7.2588 8.54437 8.52007 9.80564 8.52007 11.3653C8.52007 12.9181 7.25202 14.1862 5.69916 14.1862ZM10.907 8.96479C9.34736 8.96479 8.08608 7.70352 8.08608 6.15066C8.08608 4.59102 9.34736 3.32975 10.9002 3.32975C12.4531 3.32975 13.7211 4.59102 13.7211 6.14388C13.7279 7.69674 12.4666 8.95801 10.907 8.96479Z" fill="black"/>
|
||||
<path d="M15.6198 26.0937C15.7215 25.7275 15.8097 25.3546 15.8978 24.9613C15.9453 24.7443 15.9996 24.5205 16.047 24.3035C16.3183 23.1914 16.7455 21.9301 17.8643 20.9876C18.122 20.7502 19.2816 19.7873 21.6685 19.5907C21.7567 19.3533 21.8584 19.1024 21.9804 18.8515C22.7603 17.2173 24.1368 15.461 25.8727 13.9082C26.1779 13.6301 26.4898 13.3725 26.8085 13.1216C26.7746 12.5248 26.7068 11.9349 26.5983 11.3449C25.9338 7.77133 24.0826 4.95042 21.0921 2.90933C18.8272 1.35647 16.2979 0.644459 13.5516 0.671583C11.5512 0.691926 9.64572 1.08523 7.84197 1.92608C5.48217 3.0246 3.51566 4.59102 2.1798 6.86267C1.07449 8.70033 0.504883 10.7075 0.667628 12.8435C0.87106 15.5424 2.20692 17.6106 4.5057 19.0346C5.99074 19.9569 7.63854 20.262 9.15071 20.1874C9.80169 20.1874 10.2425 20.1942 10.6764 20.1874C10.9884 20.1806 11.2393 20.2688 11.3817 20.5604C11.5241 20.852 11.4224 21.0893 11.2325 21.3198C10.5001 22.2149 10.2492 23.2253 10.5883 24.3306C11.0494 25.8225 12.3446 26.7243 13.9449 26.6701C14.1687 26.6633 14.3925 26.6497 14.6094 26.6362C14.7858 26.5616 14.9756 26.5141 15.1655 26.4938C15.4028 26.4667 15.5317 26.4056 15.6198 26.0937ZM24.8895 12.9927C24.8895 14.5524 23.6282 15.8136 22.0686 15.8136C20.5089 15.8136 19.2477 14.5524 19.2477 12.9927C19.2477 11.4331 20.5089 10.1718 22.0686 10.1718C23.6282 10.1718 24.8895 11.4331 24.8895 12.9927ZM18.339 4.0621C19.8987 4.0621 21.1599 5.32338 21.1599 6.88301C21.1599 8.44265 19.8987 9.70393 18.339 9.70393C16.7794 9.70393 15.5181 8.44265 15.5181 6.88301C15.5181 5.32338 16.7794 4.0621 18.339 4.0621ZM5.69916 14.1862C4.13952 14.1862 2.87825 12.9249 2.87825 11.3653C2.87825 9.80564 4.13952 8.54437 5.69916 8.54437C7.2588 8.54437 8.52007 9.80564 8.52007 11.3653C8.52007 12.9181 7.25202 14.1862 5.69916 14.1862ZM10.907 8.96479C9.34736 8.96479 8.08608 7.70352 8.08608 6.15066C8.08608 4.59102 9.34736 3.32975 10.9002 3.32975C12.4531 3.32975 13.7211 4.59102 13.7211 6.14388C13.7279 7.69674 12.4666 8.95801 10.907 8.96479Z" fill="url(#paint0_linear_7_147)"/>
|
||||
<path d="M15.6198 26.0937C15.7215 25.7275 15.8097 25.3546 15.8978 24.9613C15.9453 24.7443 15.9996 24.5205 16.047 24.3035C16.3183 23.1914 16.7455 21.9301 17.8643 20.9876C18.122 20.7502 19.2816 19.7873 21.6685 19.5907C21.7567 19.3533 21.8584 19.1024 21.9804 18.8515C22.7603 17.2173 24.1368 15.461 25.8727 13.9082C26.1779 13.6301 26.4898 13.3725 26.8085 13.1216C26.7746 12.5248 26.7068 11.9349 26.5983 11.3449C25.9338 7.77133 24.0826 4.95042 21.0921 2.90933C18.8272 1.35647 16.2979 0.644459 13.5516 0.671583C11.5512 0.691926 9.64572 1.08523 7.84197 1.92608C5.48217 3.0246 3.51566 4.59102 2.1798 6.86267C1.07449 8.70033 0.504883 10.7075 0.667628 12.8435C0.87106 15.5424 2.20692 17.6106 4.5057 19.0346C5.99074 19.9569 7.63854 20.262 9.15071 20.1874C9.80169 20.1874 10.2425 20.1942 10.6764 20.1874C10.9884 20.1806 11.2393 20.2688 11.3817 20.5604C11.5241 20.852 11.4224 21.0893 11.2325 21.3198C10.5001 22.2149 10.2492 23.2253 10.5883 24.3306C11.0494 25.8225 12.3446 26.7243 13.9449 26.6701C14.1687 26.6633 14.3925 26.6497 14.6094 26.6362C14.7858 26.5616 14.9756 26.5141 15.1655 26.4938C15.4028 26.4667 15.5317 26.4056 15.6198 26.0937ZM24.8895 12.9927C24.8895 14.5524 23.6282 15.8136 22.0686 15.8136C20.5089 15.8136 19.2477 14.5524 19.2477 12.9927C19.2477 11.4331 20.5089 10.1718 22.0686 10.1718C23.6282 10.1718 24.8895 11.4331 24.8895 12.9927ZM18.339 4.0621C19.8987 4.0621 21.1599 5.32338 21.1599 6.88301C21.1599 8.44265 19.8987 9.70393 18.339 9.70393C16.7794 9.70393 15.5181 8.44265 15.5181 6.88301C15.5181 5.32338 16.7794 4.0621 18.339 4.0621ZM5.69916 14.1862C4.13952 14.1862 2.87825 12.9249 2.87825 11.3653C2.87825 9.80564 4.13952 8.54437 5.69916 8.54437C7.2588 8.54437 8.52007 9.80564 8.52007 11.3653C8.52007 12.9181 7.25202 14.1862 5.69916 14.1862ZM10.907 8.96479C9.34736 8.96479 8.08608 7.70352 8.08608 6.15066C8.08608 4.59102 9.34736 3.32975 10.9002 3.32975C12.4531 3.32975 13.7211 4.59102 13.7211 6.14388C13.7279 7.69674 12.4666 8.95801 10.907 8.96479Z" fill="#E17351"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_7_147" x1="-1.43116" y1="9.77543" x2="41.7398" y2="6.56826" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9E5BB"/>
|
||||
<stop offset="1" stop-color="#3F6972"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M37.0001 14.9723C37.0001 13.3587 35.6845 12.0487 34.0709 12.0487C33.177 12.0487 32.3674 12.4535 31.8333 13.0888L24.7661 9.01274C24.873 8.71476 24.9292 8.3943 24.9292 8.06259C24.9292 6.44902 23.6136 5.13342 22 5.13342C20.3865 5.13342 19.0709 6.44902 19.0709 8.06259C19.0709 8.3943 19.1271 8.71476 19.2339 9.01274L12.1668 13.0888C11.6327 12.4535 10.8231 12.0487 9.92917 12.0487C8.31559 12.0487 7 13.3587 7 14.9723C7 16.4003 8.02324 17.5866 9.36695 17.8452V26.1548C8.02324 26.4134 7 27.5997 7 29.0278C7 30.6413 8.31559 31.9513 9.92917 31.9513C10.8231 31.9513 11.6327 31.5465 12.1668 30.9112L19.2339 34.9873C19.1271 35.2853 19.0709 35.6057 19.0709 35.9375C19.0709 37.551 20.3865 38.8666 22 38.8666C23.6136 38.8666 24.9292 37.551 24.9292 35.9375C24.9292 35.6057 24.873 35.2853 24.7661 34.9873L31.8333 30.9112C32.3674 31.5465 33.177 31.9513 34.0709 31.9513C35.6845 31.9513 37.0001 30.6413 37.0001 29.0278C37.0001 27.5997 35.9768 26.4134 34.6331 26.1548V17.8452C35.9768 17.5866 37.0001 16.4003 37.0001 14.9723ZM24.2039 34.0147C23.6698 33.3962 22.8771 33.0083 22 33.0083C21.123 33.0083 20.3302 33.3962 19.7961 34.0147L12.7178 29.9273C12.8077 29.6462 12.8583 29.3426 12.8583 29.0278C12.8583 27.5997 11.8351 26.4134 10.4914 26.1548V17.8452C11.8351 17.5866 12.8583 16.4003 12.8583 14.9723C12.8583 14.6574 12.8077 14.3538 12.7178 14.0727L19.7961 9.98538C20.3302 10.6038 21.123 10.9918 22 10.9918C22.8771 10.9918 23.6698 10.6038 24.2039 9.98538L31.2823 14.0727C31.1923 14.3538 31.1417 14.6574 31.1417 14.9723C31.1417 16.4003 32.165 17.5866 33.5087 17.8452V26.1548C32.165 26.4134 31.1417 27.5997 31.1417 29.0278C31.1417 29.3426 31.1923 29.6462 31.2823 29.9273L24.2039 34.0147Z" fill="#3F6972"/>
|
||||
<path d="M22 13.3025C17.2043 13.3025 13.3025 17.2043 13.3025 22C13.3025 26.7958 17.2043 30.6976 22 30.6976C26.7958 30.6976 30.6976 26.7958 30.6976 22C30.6976 17.2043 26.7958 13.3025 22 13.3025ZM19.1102 23.2088L18.4693 24.6087C18.34 24.8898 18.0083 25.0135 17.7272 24.8842C17.4404 24.7549 17.3167 24.4232 17.4461 24.1365L20.0154 18.5424C20.1054 18.34 20.3077 18.2107 20.527 18.2107C20.7463 18.2107 20.9431 18.34 21.0386 18.5424L22.8153 22.4273L23.6024 24.1365C23.7317 24.4232 23.608 24.7549 23.3269 24.8842C23.2538 24.918 23.1694 24.9348 23.0964 24.9348C22.8827 24.9348 22.6747 24.8111 22.5847 24.6087L21.9438 23.2088H19.1102ZM25.587 24.3726C25.587 24.6818 25.334 24.9348 25.0248 24.9348C24.7156 24.9348 24.4626 24.6818 24.4626 24.3726V18.7729C24.4626 18.4637 24.7156 18.2107 25.0248 18.2107C25.334 18.2107 25.587 18.4637 25.587 18.7729V24.3726Z" fill="#E17351"/>
|
||||
<path d="M19.6274 22.0843H21.4265L20.527 20.1222L19.6274 22.0843Z" fill="#E17351"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg width="27" height="34" viewBox="0 0 27 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.8988 24.6458L2.31714 27.4322V6.323L13.8988 9.02498V24.6458Z" fill="#E05243"/>
|
||||
<path d="M13.5578 24.7303L24.8013 27.4322V6.323L13.5578 9.02498V24.7303Z" fill="#8C3123"/>
|
||||
<path d="M13.5585 0.665283V8.85567L18.4617 10.0378V3.11396L13.5585 0.665283ZM24.802 6.32256V27.4318L27 26.3341V7.3358L24.802 6.32256ZM13.5585 12.8242V21.0146L18.4617 20.3391V13.4153L13.5585 12.8242ZM18.4617 23.7166L13.5585 24.8987V33.0891L18.4617 30.6404V23.7166Z" fill="#E05243"/>
|
||||
<path d="M13.5578 33.0894L13.5578 24.899L8.65457 23.7169V30.6407L13.5578 33.0894ZM2.31422 27.4321L2.31422 6.32284L0.116235 7.42052L0.116235 26.4188L2.31422 27.4321ZM13.5578 20.9304V12.74L8.65457 13.4155L8.65457 20.3394L13.5578 20.9304ZM8.65457 10.0381L13.5578 8.85595V0.665562L8.65457 3.11423V10.0381Z" fill="#8C3123"/>
|
||||
<path d="M18.4628 10.0382L13.5596 10.967L8.65637 10.0382L13.5596 8.77161L18.4628 10.0382Z" fill="#5E1F18"/>
|
||||
<path d="M18.4628 23.7169L13.5596 22.7881L8.65637 23.7169L13.5596 25.0679L18.4628 23.7169Z" fill="#F2B0A9"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="24" viewBox="0 0 48 24" fill="none">
|
||||
<path d="M46.9886 13.0607C47.5744 12.4749 47.5744 11.5251 46.9886 10.9393L37.4427 1.3934C36.8569 0.807611 35.9072 0.807611 35.3214 1.3934C34.7356 1.97919 34.7356 2.92893 35.3214 3.51472L43.8067 12L35.3214 20.4853C34.7356 21.0711 34.7356 22.0208 35.3214 22.6066C35.9072 23.1924 36.8569 23.1924 37.4427 22.6066L46.9886 13.0607ZM0.927979 13.5H45.928V10.5H0.927979V13.5Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 489 B |
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 19 19" fill="none">
|
||||
<circle cx="9.5" cy="9.5" r="6.65" stroke="#7E869E" stroke-opacity="0.25" stroke-width="0.95"/>
|
||||
<path d="M7.12512 11.8747L11.8751 7.12472" stroke="#222222" stroke-width="0.95"/>
|
||||
<path d="M11.875 11.875L7.125 7.125" stroke="#222222" stroke-width="0.95"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 368 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
||||
<path fill="#F38020" d="M37,21.5c0-4.7-3.8-8.5-8.5-8.5c-0.6,0-1.2,0.1-1.8,0.2c-1.3-3-4.3-5.2-7.7-5.2c-4.7,0-8.5,3.8-8.5,8.5 c0,0.6,0.1,1.1,0.2,1.7C7.3,19.5,5,22.5,5,26c0,4.4,3.6,8,8,8h24c3.9,0,7-3.1,7-7C44,24.1,40.9,21,37,21.5z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 324 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.3602 21.9686C22.9396 21.5564 22.9396 20.888 23.3602 20.4758C23.7807 20.0636 24.4626 20.0636 24.8831 20.4758L29.0714 24.581C29.4919 24.9932 29.4919 25.6616 29.0714 26.0738L24.8831 30.1789C24.4626 30.5911 23.7807 30.5911 23.3602 30.1789C22.9396 29.7667 22.9396 29.0984 23.3602 28.6862L26.7869 25.3274L23.3602 21.9686ZM20.5752 28.6863C20.9958 29.0985 20.9958 29.7667 20.5752 30.179C20.1547 30.5912 19.4728 30.5912 19.0522 30.179L14.864 26.0739C14.4434 25.6617 14.4434 24.9933 14.864 24.5811L19.0522 20.4759C19.4728 20.0638 20.1547 20.0638 20.5752 20.4759C20.9958 20.8881 20.9958 21.5565 20.5752 21.9687L17.1485 25.3275L20.5752 28.6863ZM8 17H36V30.7222C36 33.637 33.5892 36 30.6154 36H13.3846C10.4108 36 8 33.637 8 30.7222V17Z" fill="#E17351"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 13C8 10.2386 10.4108 8 13.3846 8H30.6154C33.5892 8 36 10.2386 36 13V14H34.9231H9.07692H8V13Z" fill="#3F6972"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l140.1 0L400 115.9 400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-204.1c0-12.7-5.1-24.9-14.1-33.9L366.1 14.1c-9-9-21.2-14.1-33.9-14.1L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-32-48 0 0 32c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l32 0 0-48-32 0z"/></svg>
|
||||
|
After Width: | Height: | Size: 683 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="30" height="31" viewBox="0 0 30 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Crown">
|
||||
<path id="Vector" d="M24.302 24.0738H5.7089C5.51867 24.0738 5.33624 24.1494 5.20173 24.2839C5.06722 24.4184 4.99166 24.6008 4.99166 24.791V26.2145C4.99166 26.4047 5.06722 26.5872 5.20173 26.7217C5.33624 26.8562 5.51867 26.9317 5.7089 26.9317H24.302C24.4903 26.9318 24.6711 26.8577 24.8053 26.7256C24.9395 26.5934 25.0163 26.4138 25.0192 26.2255V24.791C25.0164 24.6017 24.9399 24.4209 24.806 24.287C24.6721 24.1531 24.4913 24.0767 24.302 24.0738ZM27.1599 9.72898C26.5746 9.72898 26.0133 9.96149 25.5994 10.3754C25.1855 10.7892 24.953 11.3506 24.953 11.9359C24.9576 12.2407 25.0252 12.5413 25.1517 12.8186L21.9186 14.7607C21.7551 14.8576 21.5741 14.9211 21.386 14.9475C21.1978 14.9738 21.0063 14.9626 20.8225 14.9143C20.6388 14.8661 20.4664 14.7818 20.3155 14.6664C20.1646 14.551 20.0381 14.4068 19.9434 14.2421L16.302 7.86415C16.6644 7.58147 16.9296 7.19269 17.0604 6.75207C17.1912 6.31145 17.1812 5.84098 17.0317 5.40633C16.8823 4.97168 16.6008 4.59454 16.2267 4.32755C15.8526 4.06056 15.4044 3.91705 14.9448 3.91705C14.4851 3.91705 14.037 4.06056 13.6628 4.32755C13.2887 4.59454 13.0073 4.97168 12.8578 5.40633C12.7083 5.84098 12.6983 6.31145 12.8291 6.75207C12.96 7.19269 13.2251 7.58147 13.5875 7.86415L9.94614 14.2421C9.85141 14.4068 9.72492 14.551 9.574 14.6664C9.42308 14.7818 9.25073 14.8661 9.06698 14.9143C8.88322 14.9626 8.69171 14.9738 8.50356 14.9475C8.31541 14.9211 8.13438 14.8576 7.97097 14.7607L4.73786 12.8186C4.86687 12.5421 4.93462 12.241 4.93648 11.9359C4.93841 11.5066 4.81189 11.0866 4.5732 10.7298C4.33451 10.373 3.99456 10.0957 3.59704 9.9337C3.19953 9.77165 2.76264 9.73221 2.34253 9.82044C1.92243 9.90867 1.53831 10.1205 1.23958 10.4288C0.940839 10.7371 0.741138 11.1277 0.666146 11.5503C0.591154 11.973 0.6443 12.4084 0.818752 12.8007C0.993204 13.1929 1.28099 13.524 1.6451 13.7513C2.00921 13.9787 2.43301 14.092 2.862 14.0766C2.97942 14.088 3.09768 14.088 3.2151 14.0766L6.44821 22.6945H23.5848L26.8068 14.0766H27.1599C27.7026 14.0376 28.2103 13.7946 28.5809 13.3964C28.9516 12.9982 29.1577 12.4744 29.1577 11.9304C29.1577 11.3863 28.9516 10.8625 28.5809 10.4643C28.2103 10.0661 27.7026 9.82308 27.1599 9.78415V9.72898Z" fill="#FFCA38"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg width="34" height="35" viewBox="0 0 34 35" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.4525 18.5456L22.9766 18.5403V16.7643C24.136 16.3531 24.9688 15.2457 24.9688 13.9465C24.9688 13.3964 24.5228 12.9508 23.9727 12.9508C23.4225 12.9508 22.9766 13.3973 22.9766 13.9474C22.9766 14.1745 22.8993 14.3835 22.7708 14.5513C22.4588 13.6609 21.8133 12.926 20.9844 12.4973C20.9577 12.2491 21.1356 11.1729 20.4189 9.9782L20.9583 9.43878C21.3473 9.04984 21.3473 8.41912 20.9583 8.03011C20.5693 7.64117 19.9386 7.64117 19.5496 8.03011L19.0013 8.57843C17.765 7.85705 16.2374 7.85573 14.9988 8.57843L14.4505 8.03011C14.0615 7.64117 13.4308 7.64117 13.0418 8.03011C12.6528 8.41905 12.6528 9.04978 13.0418 9.43878L13.5812 9.9782C12.8653 11.1714 13.0435 12.2388 13.0157 12.4973C12.1532 12.9434 11.4891 13.7211 11.1928 14.6604C11.0068 14.4793 10.8907 14.2265 10.8907 13.9465C10.8907 13.3964 10.4447 12.9508 9.8946 12.9508C9.34449 12.9508 8.8985 13.3973 8.8985 13.9474C8.8985 15.295 9.79539 16.4367 11.0235 16.808V18.5389L10.4147 18.5457C9.02939 18.561 7.90234 19.7006 7.90234 21.086C7.90234 21.6361 8.34833 22.0821 8.89844 22.0821C9.44855 22.0821 9.89453 21.6361 9.89453 21.086C9.89453 20.7869 10.1378 20.541 10.4367 20.5377L11.0234 20.5312C11.0434 20.7854 10.9079 21.8784 11.4677 23.2447C9.77108 24.1415 9.92986 25.9374 9.92621 25.9506C9.93457 26.4944 10.3793 26.9384 10.9374 26.9313C11.4875 26.9229 11.9266 26.4702 11.9182 25.9201C11.9209 25.9109 11.8361 25.1811 12.5328 24.9505C13.4047 25.932 14.5933 26.6261 15.9376 26.8683V13.6332C15.9376 13.0831 16.3836 12.6371 16.9337 12.6371C17.4838 12.6371 17.9298 13.0831 17.9298 13.6332V26.8905C19.3103 26.674 20.5346 25.9822 21.4321 24.9897C21.5276 25.0344 21.6158 25.0954 21.6922 25.1729C22.0028 25.4885 21.9439 25.8852 21.9492 25.9201C21.9407 26.4759 22.3888 26.9314 22.9455 26.9314C23.4885 26.9314 23.9327 26.4954 23.9411 25.9505C23.9355 25.9294 24.1055 24.2403 22.5076 23.305C23.0958 21.9133 22.9551 20.7974 22.9766 20.5325L23.4304 20.5376C23.7295 20.5409 23.9727 20.7869 23.9727 21.0859C23.9727 21.636 24.4187 22.082 24.9688 22.082C25.5189 22.082 25.9649 21.636 25.9649 21.0859C25.9648 19.7006 24.8378 18.561 23.4525 18.5456Z" fill="#E17351"/>
|
||||
<path d="M33.0039 16.5039H32.6061C32.1113 8.67268 25.8273 2.38873 17.9961 1.89393V1.49609C17.9961 0.945984 17.5501 0.5 17 0.5C16.4499 0.5 16.0039 0.945984 16.0039 1.49609V1.89393C8.17268 2.38873 1.88873 8.67268 1.39393 16.5039H0.996094C0.445984 16.5039 0 16.9499 0 17.5C0 18.0501 0.445984 18.4961 0.996094 18.4961H1.39393C1.88873 26.3273 8.17268 32.6113 16.0039 33.1061V33.5039C16.0039 34.054 16.4499 34.5 17 34.5C17.5501 34.5 17.9961 34.054 17.9961 33.5039V33.1061C25.8273 32.6113 32.1113 26.3273 32.6061 18.4961H33.0039C33.554 18.4961 34 18.0501 34 17.5C34 16.9499 33.554 16.5039 33.0039 16.5039ZM17.9961 31.11V30.4492C17.9961 29.8991 17.5501 29.4531 17 29.4531C16.4499 29.4531 16.0039 29.8991 16.0039 30.4492V31.11C9.27151 30.6219 3.87806 25.2285 3.39004 18.4961H4.05078C4.60089 18.4961 5.04688 18.0501 5.04688 17.5C5.04688 16.9499 4.60089 16.5039 4.05078 16.5039H3.39004C3.87806 9.77151 9.27151 4.37806 16.0039 3.89004V4.55078C16.0039 5.10089 16.4499 5.54688 17 5.54688C17.5501 5.54688 17.9961 5.10089 17.9961 4.55078V3.89004C24.7285 4.37806 30.1219 9.77151 30.61 16.5039H29.9492C29.3991 16.5039 28.9531 16.9499 28.9531 17.5C28.9531 18.0501 29.3991 18.4961 29.9492 18.4961H30.61C30.1219 25.2285 24.7285 30.6219 17.9961 31.11Z" fill="#3F6972"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="65.2 173.5 32 32" width="64" height="64" fill="#0080ff"><path d="M81.202 205.5v-6.2c6.568 0 11.666-6.5 9.144-13.418a9.27 9.27 0 0 0-5.533-5.531c-6.912-2.502-13.425 2.575-13.425 9.14H65.2c0-10.463 10.124-18.622 21.1-15.195 4.8 1.505 8.618 5.313 10.105 10.1 3.43 10.99-4.717 21.107-15.203 21.107z"/><path d="M75.05 199.317v-6.165h6.168v6.165zm-4.753 4.75v-4.75h4.753v4.75h-4.753zm0-4.75h-3.973v-3.97h3.973v3.97z"/></svg>
|
||||
|
After Width: | Height: | Size: 467 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="27" viewBox="0 0 32 27" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.5662 4.95504L7.78101 9.91008L15.5662 14.8651L7.78101 19.8202L3.05176e-05 14.8259L7.7852 9.87088L3.05176e-05 4.95504L7.7852 0L15.5662 4.95504ZM7.7438 21.3924L15.529 16.4374L23.3141 21.3924L15.5295 26.3433L7.74432 21.3882L7.7438 21.3924ZM15.5662 14.8259L23.3514 9.87088L15.5662 4.95504L23.3147 0L31.0998 4.95504L23.3147 9.91008L31.0998 14.8651L23.3147 19.8202L15.5709 14.8233L15.5662 14.8259Z" fill="#0061FF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 525 B |
@@ -0,0 +1,12 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19.2151 6.03436C19.6234 6.03436 19.9276 6.40928 19.8958 6.81635C19.8828 6.98453 19.8761 7.1545 19.8761 7.32603C19.8761 8.99386 20.5082 10.514 21.5461 11.66C22.1495 12.3262 22.89 12.866 23.7232 13.2347C24.5217 13.5881 25.405 13.7844 26.3344 13.7844C27.3261 13.7844 28.2656 13.5609 29.1051 13.1615C29.586 12.9328 30.2094 13.2536 30.2094 13.786V22.826C30.2094 24.9662 28.4746 26.701 26.3344 26.701H5.66772C3.52763 26.701 1.79272 24.9662 1.79272 22.826V9.90936C1.79272 7.76927 3.52763 6.03436 5.66772 6.03436H19.2151Z" fill="#C2D3C7"/>
|
||||
<path d="M19.2151 6.03436C19.6234 6.03436 19.9276 6.40928 19.8958 6.81635C19.8828 6.98453 19.8761 7.1545 19.8761 7.32603C19.8761 8.99386 20.5082 10.514 21.5461 11.66C22.1495 12.3262 22.89 12.866 23.7232 13.2347C24.5217 13.5881 25.405 13.7844 26.3344 13.7844C27.3261 13.7844 28.2656 13.5609 29.1051 13.1615C29.586 12.9328 30.2094 13.2536 30.2094 13.786V22.826C30.2094 24.9662 28.4746 26.701 26.3344 26.701H5.66772C3.52763 26.701 1.79272 24.9662 1.79272 22.826V9.90936C1.79272 7.76927 3.52763 6.03436 5.66772 6.03436H19.2151Z" fill="url(#paint0_linear_54_158)"/>
|
||||
<path d="M19.2151 6.03436C19.6234 6.03436 19.9276 6.40928 19.8958 6.81635C19.8828 6.98453 19.8761 7.1545 19.8761 7.32603C19.8761 8.99386 20.5082 10.514 21.5461 11.66C22.1495 12.3262 22.89 12.866 23.7232 13.2347C24.5217 13.5881 25.405 13.7844 26.3344 13.7844C27.3261 13.7844 28.2656 13.5609 29.1051 13.1615C29.586 12.9328 30.2094 13.2536 30.2094 13.786V22.826C30.2094 24.9662 28.4746 26.701 26.3344 26.701H5.66772C3.52763 26.701 1.79272 24.9662 1.79272 22.826V9.90936C1.79272 7.76927 3.52763 6.03436 5.66772 6.03436H19.2151Z" fill="#E17351"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.3344 11.201C28.4746 11.201 30.2094 9.46609 30.2094 7.32599C30.2094 5.18589 28.4746 3.45099 26.3344 3.45099C24.1942 3.45099 22.4594 5.18589 22.4594 7.32599C22.4594 9.46609 24.1942 11.201 26.3344 11.201ZM16.7992 15.3897L21.5461 11.6599C22.1495 12.3262 22.89 12.866 23.7232 13.2347L18.3952 17.421C16.9901 18.525 15.0122 18.525 13.6071 17.421L6.16143 11.5709C5.60049 11.1301 5.50305 10.3181 5.94378 9.75719C6.38452 9.19626 7.19653 9.09881 7.75746 9.53954L15.2031 15.3897C15.6714 15.7577 16.3308 15.7577 16.7992 15.3897Z" fill="#3F6972"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_54_158" x1="-0.456639" y1="13.2709" x2="46.2016" y2="8.5352" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9E5BB"/>
|
||||
<stop offset="1" stop-color="#3F6972"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,9 @@
|
||||
<svg width="67" height="67" viewBox="0 0 67 67" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Doc">
|
||||
<path id="Vector" d="M35.6721 39.729H35.6855C35.9958 39.729 36.2731 39.656 36.5143 39.5213C36.5539 39.4992 36.5854 39.4664 36.6229 39.4416C36.6999 39.3893 36.779 39.3404 36.8487 39.2754C36.9465 39.1823 37.0349 39.0758 37.1153 38.9592C37.1187 38.9538 37.1234 38.9505 37.1274 38.9451C37.4604 38.454 37.6386 37.7632 37.6379 36.9673C37.6379 35.5074 36.9498 34.2524 35.6835 34.2524C35.1985 34.2524 34.7971 34.4347 34.4836 34.7422C33.979 35.2387 33.7064 36.0648 33.7064 37.0021C33.7064 38.5344 34.442 39.729 35.6721 39.729Z" fill="#00AEEF"/>
|
||||
<path id="Vector_2" d="M43.4803 13.3926V3.34998H13.4757C12.6097 3.35015 11.7793 3.69428 11.167 4.30668C10.5548 4.91907 10.2108 5.74959 10.2108 6.61556V60.3844C10.211 61.2503 10.555 62.0807 11.1672 62.6931C11.7795 63.3054 12.6098 63.6496 13.4757 63.65H53.5223C54.3883 63.6496 55.2188 63.3055 55.8312 62.6932C56.4437 62.0808 56.788 61.2504 56.7885 60.3844V16.6582H46.7459C45.8798 16.6582 45.0492 16.3141 44.4368 15.7017C43.8244 15.0893 43.4803 14.2587 43.4803 13.3926ZM21.2604 41.1896H21.247C20.6313 41.1896 20.1851 40.7199 20.1851 40.08C20.1851 39.4167 20.6313 38.9585 21.2712 38.9585C21.8983 38.9585 22.3324 39.4047 22.3445 40.08C22.3452 40.7192 21.9117 41.1896 21.2604 41.1896ZM30.8247 36.7984C30.8247 37.9649 30.5058 38.8606 30.0207 39.5159C29.8645 39.7271 29.6852 39.9202 29.486 40.0914C28.6298 40.8036 27.3152 41.1407 25.7226 41.1407C24.7692 41.1407 24.0818 41.0804 23.6356 41.0187V33.0457C24.3103 32.9244 25.1913 32.8641 26.1086 32.8641C27.6643 32.8641 28.6773 33.1174 29.4492 33.709C29.6602 33.8658 29.8525 34.0467 30.0207 34.2524C30.5265 34.8708 30.8247 35.7123 30.8247 36.7984ZM35.6118 41.1896H35.5984C33.1978 41.1896 31.7747 39.3678 31.7747 37.0516C31.7747 35.4624 32.4447 34.1385 33.5717 33.4075C34.172 33.0169 34.901 32.7925 35.7324 32.7925C38.2309 32.7925 39.593 34.6624 39.593 36.9063C39.593 39.5836 37.9883 41.1896 35.6118 41.1896ZM45.0669 39.6566C45.424 39.6566 45.7898 39.6104 46.1101 39.5387C46.297 39.4965 46.4732 39.4489 46.6112 39.3906L46.8765 40.8378L46.8759 40.8385C46.5496 40.9946 45.7777 41.1882 44.8016 41.1882C41.9909 41.1882 40.543 39.4268 40.543 37.0985C40.543 35.4262 41.2646 34.2088 42.3741 33.5027C43.1058 33.037 44.0049 32.7911 44.9831 32.7911C45.9359 32.7911 46.6595 32.9847 46.9851 33.1536L46.5992 34.6015C46.2387 34.4453 45.7175 34.3006 45.0541 34.3006C43.607 34.3006 42.4726 35.181 42.4726 37.0021C42.4733 38.6315 43.4381 39.6566 45.0669 39.6566Z" fill="#00AEEF"/>
|
||||
<path id="Vector_3" d="M28.8562 36.4996C28.8489 36.4158 28.8502 36.324 28.8375 36.2456C28.6264 34.915 27.6944 34.2772 26.3008 34.2772C25.9029 34.2772 25.6255 34.3134 25.4687 34.3489V39.668C25.586 39.6955 25.7648 39.7022 25.939 39.7042L26.1086 39.7048C27.3661 39.7142 28.2981 39.1997 28.6854 38.1236C28.6994 38.0841 28.7048 38.0365 28.7175 37.9957C28.767 37.8464 28.8053 37.6937 28.8321 37.5387C28.8475 37.4409 28.8475 37.327 28.8556 37.2218C28.8656 37.1012 28.883 36.9873 28.883 36.858C28.883 36.73 28.8663 36.6175 28.8562 36.4996ZM43.4803 3.34998V13.3926C43.4803 14.2586 43.8243 15.0891 44.4365 15.7015C45.0488 16.3139 45.8793 16.658 46.7452 16.6582H56.7885L43.4803 3.34998Z" fill="#00AEEF"/>
|
||||
<path id="Vector_4" opacity="0.6" d="M43.4803 3.34998V13.3926C43.4803 14.2586 43.8243 15.0891 44.4365 15.7015C45.0488 16.3139 45.8793 16.658 46.7452 16.6582H56.7885L43.4803 3.34998Z" fill="white"/>
|
||||
<path id="Vector_5" d="M21.2718 38.9578C20.632 38.9578 20.1858 39.4161 20.1858 40.0794C20.1858 40.7192 20.632 41.1889 21.2477 41.1889H21.2604C21.9117 41.1889 22.3452 40.7192 22.3452 40.0794C22.3331 39.4047 21.899 38.9578 21.2718 38.9578ZM29.4492 33.7097C28.6773 33.1181 27.6643 32.8648 26.1086 32.8648C25.1913 32.8648 24.3103 32.9251 23.6356 33.0464V41.0194C24.0818 41.081 24.7692 41.1413 25.7226 41.1413C27.3152 41.1413 28.6298 40.8037 29.486 40.0921C29.6852 39.9209 29.8645 39.7278 30.0207 39.5166C30.5058 38.8613 30.8247 37.9662 30.8247 36.7991C30.8247 35.7137 30.5265 34.8715 30.0207 34.2537C29.8537 34.0492 29.6617 33.8665 29.4492 33.7097ZM28.8321 37.5388C28.805 37.6936 28.7667 37.8464 28.7175 37.9957C28.7048 38.0372 28.6994 38.0848 28.6854 38.1237C28.2981 39.1997 27.3661 39.7142 26.1086 39.7049L25.9391 39.7042C25.7655 39.7029 25.5866 39.6955 25.4687 39.6687V34.3489C25.6255 34.3127 25.9029 34.2772 26.3009 34.2772C27.6945 34.2772 28.6258 34.9144 28.8375 36.2457C28.8502 36.324 28.8489 36.4158 28.8562 36.4996C28.867 36.6182 28.883 36.7307 28.883 36.8587C28.883 36.988 28.8656 37.1019 28.8556 37.2225C28.8475 37.327 28.8482 37.4409 28.8321 37.5388ZM35.7324 32.7925C34.9016 32.7925 34.1727 33.0169 33.5717 33.4075C32.4454 34.1385 31.7761 35.4624 31.7761 37.051C31.7761 39.3672 33.1992 41.1896 35.5998 41.1896H35.6125C37.989 41.1896 39.593 39.5843 39.593 36.9063C39.593 34.6618 38.2309 32.7925 35.7324 32.7925ZM33.7057 37.0034C33.7057 36.0654 33.9784 35.24 34.4836 34.7435C34.6407 34.5859 34.8279 34.4613 35.034 34.3772C35.2401 34.2931 35.4609 34.2511 35.6835 34.2537C36.9498 34.2537 37.6379 35.5087 37.6379 36.9686C37.6386 37.7645 37.4604 38.4553 37.1274 38.9464C37.1234 38.9518 37.1187 38.9551 37.1153 38.9605C37.0349 39.0771 36.9465 39.1836 36.8487 39.2767C36.779 39.3417 36.6999 39.3906 36.6229 39.4429C36.5854 39.4677 36.5532 39.5005 36.5143 39.5226C36.2731 39.6573 35.9951 39.731 35.6842 39.731H35.6715C34.4407 39.7297 33.7057 38.5357 33.7057 37.0034ZM45.0542 34.3006C45.7168 34.3006 46.238 34.4454 46.5985 34.6015L46.9844 33.1543C46.6595 32.9854 45.9359 32.7918 44.9831 32.7918C44.0049 32.7918 43.1058 33.0377 42.3741 33.5027C41.2646 34.2089 40.543 35.4262 40.543 37.0986C40.543 39.4275 41.9909 41.1882 44.8016 41.1882C45.7778 41.1882 46.5489 40.9946 46.8759 40.8385L46.6106 39.3913C46.4479 39.4544 46.2803 39.5037 46.1094 39.5387C45.7669 39.6151 45.4172 39.6546 45.0662 39.6566C43.4368 39.6566 42.4726 38.6322 42.4726 37.0028C42.4733 35.1824 43.607 34.3006 45.0542 34.3006Z" fill="white"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1,43 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="203" height="50" viewBox="0 0 203 50" fill="none">
|
||||
<path d="M15.2518 45.9715C14.488 45.9734 13.7374 45.772 13.0771 45.3881C12.7782 45.2167 12.5013 45.0095 12.2526 44.7709C11.6317 44.1821 11.2002 43.4217 11.0134 42.5866L5.5454 11.8039C5.40405 11.1746 5.40381 10.5217 5.54471 9.89228C5.6856 9.26284 5.96413 8.67241 6.36029 8.16339C6.76748 7.64433 7.28671 7.22401 7.87918 6.93382C8.47136 6.64701 9.121 6.49862 9.77898 6.49986H20.3871C21.8461 6.49811 23.2929 6.7662 24.6544 7.29063C26.2061 7.88398 27.6144 8.79934 28.7867 9.97641L28.9314 10.1259C29.2787 10.4731 29.6791 10.7628 30.1176 10.9842C30.7627 11.3013 31.472 11.4663 32.191 11.4664H47.4811C48.1335 11.4653 48.7778 11.6113 49.366 11.8936C49.9542 12.1759 50.4712 12.5872 50.8785 13.0969C51.2858 13.6066 51.5729 14.2016 51.7185 14.8376C51.8641 15.4736 51.8644 16.1343 51.7195 16.7704L47.3798 42.5914C47.1612 43.5506 46.6232 44.407 45.8539 45.0203C45.0847 45.6335 44.13 45.9673 43.1462 45.9667L15.2518 45.9715Z" fill="url(#paint0_linear_50_44)"/>
|
||||
<path d="M20.3719 6.65885C21.9141 6.65703 23.4415 6.9598 24.8664 7.54978C26.2913 8.13976 27.5857 9.00534 28.6752 10.0968L28.8247 10.2415C29.2674 10.6847 29.7937 11.0357 30.3731 11.2741C30.9525 11.5125 31.5734 11.6335 32.1999 11.6302H47.49C48.1225 11.631 48.7466 11.7742 49.3162 12.0492C49.8857 12.3241 50.3861 12.7236 50.7802 13.2182C51.1743 13.7128 51.4521 14.2898 51.5928 14.9064C51.7336 15.5229 51.7338 16.1633 51.5934 16.7799L47.2538 42.5817C47.1281 43.1444 46.8867 43.6748 46.545 44.1391C46.1563 44.6705 45.6485 45.1034 45.0624 45.4032C44.4762 45.703 43.828 45.8612 43.1697 45.8653H15.2511C14.2974 45.8652 13.3721 45.5411 12.6266 44.9463C11.8811 44.3515 11.3597 43.5212 11.1477 42.5913L5.67493 11.7652C5.54017 11.1514 5.5447 10.5151 5.68822 9.9033C5.83173 9.29147 6.11057 8.71958 6.50423 8.22971C6.89788 7.73983 7.39635 7.34445 7.96295 7.0726C8.52955 6.80075 9.14989 6.65937 9.77833 6.65885H20.3864M20.3864 6.38883H9.77833C8.59113 6.39011 7.45299 6.86262 6.61396 7.70255C5.77494 8.54248 5.30365 9.68113 5.30365 10.8683C5.3036 11.193 5.34082 11.5166 5.41455 11.8327L10.8825 42.6202C11.1076 43.6109 11.6624 44.4959 12.456 45.1301C13.2497 45.7643 14.2352 46.1103 15.2511 46.1113H43.1166C43.8203 46.1095 44.5136 45.9417 45.1403 45.6217C45.767 45.3016 46.3094 44.8383 46.7234 44.2693C47.087 43.7749 47.3432 43.2099 47.4756 42.6106L51.8152 16.7944C51.9629 16.1393 51.9611 15.4595 51.8102 14.8052C51.6594 14.1509 51.3631 13.5389 50.9436 13.0147C50.524 12.4904 49.9918 12.0673 49.3864 11.7767C48.7811 11.4862 48.1181 11.3355 47.4466 11.3361H32.1758C31.4773 11.3334 30.7889 11.1684 30.1651 10.8539C29.7377 10.6411 29.3483 10.3592 29.0127 10.0197L28.868 9.87504C27.753 8.75836 26.4286 7.87263 24.9707 7.26862C23.5128 6.66461 21.95 6.35416 20.3719 6.35507L20.3864 6.38883Z" fill="#A9E5BB"/>
|
||||
<path d="M23.8341 9.70633L49.0958 3.18718C49.8706 2.98734 50.6828 2.9821 51.4602 3.17192C52.2376 3.36173 52.956 3.74072 53.5515 4.27518C54.147 4.80964 54.6012 5.483 54.8738 6.23537C55.1463 6.98774 55.2286 7.79579 55.1134 8.58766L52.5868 25.8836C52.4673 26.7172 52.1352 27.506 51.6224 28.174C51.2151 28.6949 50.7055 29.127 50.1251 29.4437C49.5447 29.7605 48.9056 29.9552 48.2471 30.016L33.9552 31.4143C33.4058 31.4688 32.8512 31.4281 32.3157 31.2938C31.1716 31.0137 30.1678 30.3285 29.4901 29.365L21.0519 17.185C20.6059 16.5419 20.3219 15.8006 20.2242 15.0241C20.1264 14.2476 20.2179 13.459 20.4906 12.7254C20.7634 11.9919 21.2094 11.3351 21.7908 10.8111C22.3721 10.2871 23.0714 9.9114 23.8293 9.71597L23.8341 9.70633Z" fill="#3F6972"/>
|
||||
<path d="M33.4884 31.5782C33.0835 31.5789 32.6801 31.5287 32.2877 31.4287C31.1126 31.1345 30.0845 30.4234 29.3946 29.4276L20.9467 17.2669C20.4884 16.6059 20.1966 15.844 20.0962 15.0459C19.9958 14.2479 20.0897 13.4374 20.3701 12.6835C20.6504 11.9296 21.1088 11.2547 21.7063 10.7161C22.3037 10.1776 23.0224 9.7914 23.8013 9.5905L49.063 3.07136C49.8598 2.86547 50.6952 2.85987 51.4948 3.05503C52.2944 3.25019 53.0332 3.64005 53.6456 4.18992C54.258 4.73978 54.7249 5.43258 55.0047 6.20658C55.2846 6.98059 55.3686 7.81178 55.2494 8.62613L52.7179 25.9221C52.5588 27.0258 52.0336 28.044 51.2265 28.8135C50.4195 29.5829 49.3773 30.059 48.2674 30.1654L33.9754 31.5685C33.8114 31.5685 33.6523 31.5782 33.4884 31.5782ZM23.8447 9.70624L23.8784 9.83642C23.1408 10.0252 22.4598 10.3896 21.8934 10.8985C21.3271 11.4075 20.8923 12.0459 20.6261 12.7592C20.3599 13.4726 20.2702 14.2397 20.3646 14.9953C20.4591 15.7508 20.7349 16.4723 21.1685 17.0981L29.6116 29.2781C30.2673 30.2225 31.2442 30.8961 32.3601 31.1731C32.8822 31.2985 33.4213 31.3376 33.9561 31.2888L48.2432 29.8857C49.2933 29.7828 50.2787 29.3314 51.0424 28.6035C51.8062 27.8755 52.3043 26.913 52.4576 25.8691L54.9842 8.58756C55.0998 7.81635 55.0225 7.02852 54.7593 6.29446C54.496 5.5604 54.0551 4.903 53.4757 4.38098C52.8964 3.85896 52.1968 3.48859 51.4394 3.30298C50.6819 3.11736 49.8903 3.12227 49.1353 3.31728L23.8688 9.83642L23.8447 9.70624Z" fill="#A9E5BB"/>
|
||||
<path d="M28.4009 11.0854L54.5835 7.07359C55.4024 6.94653 56.2402 7.03139 57.017 7.32005C57.7938 7.60872 58.4836 8.09156 59.0208 8.72255C59.558 9.35354 59.9246 10.1116 60.0856 10.9245C60.2466 11.7374 60.1967 12.578 59.9406 13.3661L54.5208 30.1655C54.212 31.1475 53.597 32.0049 52.7658 32.6122C51.9347 33.2195 50.9309 33.5449 49.9015 33.5407H35.3588C34.449 33.5421 33.5573 33.2872 32.7855 32.8054C32.0138 32.3236 31.3933 31.6343 30.995 30.8164L24.7507 18.0288C24.4138 17.3426 24.2437 16.5864 24.2542 15.822C24.2648 15.0575 24.4557 14.3063 24.8115 13.6296C25.1672 12.9529 25.6777 12.3698 26.3015 11.9276C26.9252 11.4855 27.6445 11.1969 28.4009 11.0854Z" fill="#003844"/>
|
||||
<path d="M17.7105 11.341H55.6296C56.3055 11.3412 56.9727 11.4934 57.5819 11.7863C58.1911 12.0791 58.7266 12.5053 59.1488 13.0331C59.5711 13.5609 59.8693 14.1769 60.0213 14.8355C60.1733 15.4941 60.1753 16.1785 60.0271 16.8379L55.6874 42.5915C55.5528 43.1985 55.2916 43.7703 54.9207 44.2695C54.503 44.8403 53.9565 45.3046 53.3256 45.6247C52.6947 45.9447 51.9973 46.1115 51.2899 46.1114H16.3941C15.7751 46.113 15.1625 45.9869 14.5945 45.7409C14.0265 45.4948 13.5154 45.1343 13.0931 44.6817C12.6708 44.2291 12.3465 43.6942 12.1404 43.1106C11.9343 42.5269 11.8509 41.907 11.8953 41.2896L13.2165 15.5312C13.2936 14.3923 13.8008 13.3253 14.6352 12.5464C15.4696 11.7674 16.569 11.3348 17.7105 11.3362V11.341Z" fill="url(#paint1_linear_50_44)"/>
|
||||
<path d="M51.2945 46.2417H16.394C15.7577 46.2426 15.1281 46.1124 14.5443 45.8593C13.9605 45.6062 13.4351 45.2356 13.0008 44.7705C12.5666 44.3055 12.2327 43.756 12.0201 43.1563C11.8075 42.5566 11.7206 41.9195 11.765 41.2848L13.0814 15.5313C13.1326 14.8068 13.3525 14.1042 13.7233 13.4797C14.0942 12.8552 14.6058 12.326 15.2174 11.9342C15.9616 11.4578 16.8268 11.2051 17.7103 11.2061H55.6294C56.3779 11.2061 57.1153 11.3872 57.7786 11.7339C58.4419 12.0807 59.0115 12.5829 59.4387 13.1975C59.8095 13.7244 60.0651 14.3234 60.1889 14.9557C60.3127 15.5879 60.3018 16.2392 60.1571 16.867L55.8174 42.6157C55.5857 43.6439 55.0113 44.5627 54.1886 45.2216C53.3659 45.8805 52.3437 46.2402 51.2897 46.2417H51.2945ZM17.7103 11.4809C16.6047 11.4788 15.5399 11.8988 14.7334 12.6551C13.9269 13.4114 13.4395 14.4471 13.3707 15.5506L12.0495 41.3041C12.0079 41.9004 12.0892 42.4989 12.2882 43.0625C12.4872 43.6262 12.7998 44.1429 13.2066 44.5809C13.6134 45.0189 14.1057 45.3687 14.6531 45.6088C15.2006 45.8488 15.7914 45.974 16.3892 45.9765H51.2897C52.2831 45.9819 53.2482 45.6464 54.024 45.026C54.7998 44.4055 55.3392 43.5377 55.5522 42.5674L59.8919 16.8187C60.0287 16.2269 60.0398 15.6129 59.9243 15.0165C59.8088 14.4202 59.5695 13.8547 59.2217 13.3566C58.8184 12.7777 58.2811 12.3047 57.6556 11.9781C57.0301 11.6516 56.335 11.481 55.6294 11.4809H17.7103Z" fill="#3F6972"/>
|
||||
<path d="M45.5718 28.77C45.5718 23.561 41.3443 19.3335 36.1353 19.3335C30.9263 19.3335 26.6988 23.561 26.6988 28.77C26.6988 33.9789 30.9263 38.2065 36.1353 38.2065C41.3443 38.2065 45.5718 33.9789 45.5718 28.77ZM36.1353 20.2866C40.8252 20.2866 44.6187 24.08 44.6187 28.77C44.6187 33.4599 40.8252 37.2534 36.1353 37.2534C31.4454 37.2534 27.6519 33.4599 27.6519 28.77C27.6519 24.08 31.4454 20.2866 36.1353 20.2866ZM34.2574 33.3184L31.3793 25.571C31.8417 25.5427 32.3701 25.4955 32.3701 25.4955C32.7759 25.4483 32.7287 24.5424 32.3135 24.5613C32.3135 24.5613 31.0962 24.6557 30.3035 24.6557C30.162 24.6557 29.9921 24.6557 29.8128 24.6462C31.1717 22.5985 33.4931 21.2491 36.1353 21.2491C38.1075 21.2491 39.9005 21.9946 41.2405 23.2213C40.6743 23.1458 39.8722 23.5516 39.8722 24.5613C39.8722 25.1841 40.2307 25.7125 40.6176 26.3354C40.9102 26.8449 41.0895 27.4866 41.0895 28.4208C41.0895 29.6853 39.891 32.6484 39.891 32.6484L37.3337 25.571C37.7867 25.5427 38.0415 25.42 38.0415 25.42C38.4472 25.3728 38.4001 24.382 37.9943 24.4009C37.9943 24.4009 36.7675 24.5047 35.9749 24.5047C35.2388 24.5047 33.9838 24.4009 33.9838 24.4009C33.578 24.382 33.5308 25.4011 33.9366 25.42L34.7293 25.4955L35.7861 28.3642L34.2574 33.3184ZM39.9382 35.3472L42.4011 28.77C42.4011 28.77 43.0334 27.1752 42.7692 25.1747C43.3637 26.2504 43.6562 27.4583 43.6562 28.77C43.6562 31.5632 42.1841 34.0355 39.9382 35.3472ZM29.2278 25.722L32.8325 35.6114C30.313 34.3847 28.6144 31.7613 28.6144 28.77C28.6144 27.6753 28.8031 26.6656 29.2278 25.722ZM36.258 29.9967L38.4189 35.8945C37.7112 36.1493 36.9374 36.2909 36.1353 36.2909C35.4559 36.2909 34.8048 36.1871 34.1914 36.0078L36.258 29.9967Z" fill="url(#paint2_linear_50_44)"/>
|
||||
<path d="M72.9445 9.78833H75.5001L80.9005 22.4746H78.0074L76.8502 19.678H71.5461L70.3937 22.4987H67.5681L72.9445 9.78833ZM75.8617 17.2043L74.2078 13.1202L72.5346 17.2043H75.8617Z" fill="#003844"/>
|
||||
<path d="M81.7689 9.87994H86.6776C90.6411 9.87994 93.3751 12.5946 93.3751 16.1484V16.1821C93.3751 19.7262 90.6411 22.4794 86.6776 22.4794H81.7689V9.87994ZM86.6776 19.9769C87.181 20.0066 87.6851 19.93 88.1569 19.752C88.6288 19.574 89.0579 19.2987 89.4163 18.9439C89.7747 18.5891 90.0544 18.1629 90.2372 17.6928C90.42 17.2228 90.5018 16.7196 90.4772 16.2159V16.1773C90.5028 15.6718 90.4221 15.1665 90.2402 14.6941C90.0582 14.2218 89.7791 13.7929 89.421 13.4352C89.0628 13.0775 88.6336 12.799 88.161 12.6176C87.6884 12.4363 87.1831 12.3562 86.6776 12.3825H84.5367V19.9769H86.6776Z" fill="#003844"/>
|
||||
<path d="M92.8739 9.87994H95.931L99.2243 18.7522L102.518 9.87994H105.507L100.415 22.5711H97.9658L92.8739 9.87994Z" fill="#003844"/>
|
||||
<path d="M108.892 9.78836H111.447L116.843 22.4747H113.95L112.783 19.678H107.479L106.327 22.4988H103.501L108.892 9.78836ZM111.785 17.2044L110.112 13.1203L108.443 17.2044H111.785Z" fill="#003844"/>
|
||||
<path d="M117.711 9.87988H120.267L126.169 17.6334V9.87988H128.903V22.4746H126.545L120.445 14.4703V22.4746H117.711V9.87988Z" fill="#003844"/>
|
||||
<path d="M130.291 16.2158V16.1772C130.276 15.313 130.436 14.4547 130.761 13.654C131.087 12.8532 131.571 12.1266 132.184 11.5179C132.798 10.9093 133.528 10.4311 134.332 10.1123C135.135 9.79349 135.995 9.64062 136.859 9.66288C137.776 9.6152 138.694 9.76241 139.551 10.0948C140.408 10.4273 141.184 10.9374 141.83 11.5916L140.065 13.6264C139.223 12.7398 138.066 12.2202 136.844 12.1799C134.718 12.1799 133.189 13.9447 133.189 16.1049V16.1386C133.189 18.2988 134.684 20.0974 136.844 20.0974C138.291 20.0974 139.163 19.5236 140.152 18.6219L141.917 20.406C141.283 21.1474 140.488 21.7349 139.593 22.1242C138.699 22.5135 137.727 22.6943 136.753 22.653C135.902 22.6672 135.058 22.5106 134.269 22.1925C133.48 21.8744 132.763 21.4011 132.161 20.8008C131.558 20.2005 131.082 19.4854 130.761 18.6978C130.44 17.9102 130.28 17.0662 130.291 16.2158Z" fill="#003844"/>
|
||||
<path d="M143.055 9.87994H152.554V12.3439H145.804V14.8995H151.744V17.3683H145.808V20.0107H152.646V22.4746H143.055V9.87994Z" fill="#003844"/>
|
||||
<path d="M154.034 9.87988H158.948C162.906 9.87988 165.64 12.5946 165.64 16.1483V16.182C165.64 19.7261 162.906 22.4794 158.948 22.4794H154.034V9.87988ZM158.948 19.9768C159.451 20.0058 159.954 19.9287 160.426 19.7504C160.897 19.5721 161.325 19.2967 161.683 18.942C162.041 18.5873 162.32 18.1612 162.503 17.6916C162.685 17.2219 162.767 16.7191 162.742 16.2158V16.1772C162.768 15.6721 162.687 15.1673 162.506 14.6953C162.324 14.2233 162.045 13.7946 161.688 13.437C161.33 13.0794 160.902 12.8008 160.43 12.6191C159.958 12.4375 159.453 12.3568 158.948 12.3824H156.802V19.9768H158.948Z" fill="#003844"/>
|
||||
<path d="M68.6295 27.6195H78.2201V30.1414H71.3972V32.8223H77.4101V35.3393H71.3972V40.219H68.6295V27.6195Z" fill="#3F6972"/>
|
||||
<path d="M79.4788 27.6195H82.2513V40.219H79.4788V27.6195Z" fill="#3F6972"/>
|
||||
<path d="M84.3342 27.6196H87.1019V37.6972H93.3703V40.2191H84.3342V27.6196Z" fill="#3F6972"/>
|
||||
<path d="M94.3826 27.6195H103.886V30.0835H97.1359V32.6391H103.076V35.1079H97.1359V37.7503H103.978V40.219H94.3826V27.6195Z" fill="#3F6972"/>
|
||||
<path d="M109.683 27.6195H112.673L115.98 32.9236L119.293 27.6195H122.283V40.219H119.534V31.993L115.985 37.3742H115.913L112.407 32.046V40.2431H109.688L109.683 27.6195Z" fill="#3F6972"/>
|
||||
<path d="M128.545 27.5327H131.106L136.506 40.2189H133.613L132.461 37.3933H127.123L125.971 40.2189H123.145L128.545 27.5327ZM131.439 34.9438L129.765 30.8597L128.092 34.9438H131.439Z" fill="#3F6972"/>
|
||||
<path d="M137.374 27.6196H139.93L145.832 35.3779V27.6196H148.566V40.2191H146.213L140.099 32.2148V40.2191H137.374V27.6196Z" fill="#3F6972"/>
|
||||
<path d="M154.825 27.5327H157.38L162.776 40.2189H159.883L158.735 37.3933H153.402L152.25 40.2189H149.429L154.825 27.5327ZM157.718 34.9438L156.045 30.8597L154.372 34.9438H157.718Z" fill="#3F6972"/>
|
||||
<path d="M162.275 33.9554V33.9168C162.268 33.0511 162.434 32.1927 162.765 31.3925C163.095 30.5923 163.583 29.8666 164.199 29.2583C164.815 28.6499 165.546 28.1714 166.351 27.8509C167.155 27.5305 168.015 27.3748 168.881 27.3928C170.694 27.2967 172.471 27.9186 173.828 29.1239L172.092 31.2503C171.207 30.4058 170.023 29.9464 168.799 29.9725C166.783 29.9725 165.183 31.7566 165.183 33.8975V33.9313C165.183 36.2361 166.764 37.9286 168.997 37.9286C169.924 37.9579 170.837 37.6929 171.605 37.1716V35.373H168.818V32.9621H174.291V38.4349C172.797 39.7288 170.886 40.4394 168.91 40.436C164.975 40.436 162.275 37.6778 162.275 33.9554Z" fill="#3F6972"/>
|
||||
<path d="M175.863 27.6195H185.367V30.0835H178.616V32.6391H184.556V35.1079H178.616V37.7503H185.458V40.219H175.863V27.6195Z" fill="#3F6972"/>
|
||||
<path d="M186.843 27.6196H192.629C194.23 27.6196 195.469 28.068 196.298 28.8974C196.664 29.2823 196.947 29.7369 197.133 30.234C197.319 30.731 197.402 31.2604 197.379 31.7905V31.8291C197.419 32.6861 197.177 33.5328 196.689 34.2386C196.201 34.9444 195.495 35.4701 194.678 35.7347L197.755 40.2335H194.519L191.819 36.2025H189.639V40.2335H186.867L186.843 27.6196ZM192.422 33.7385C193.772 33.7385 194.548 33.02 194.548 31.9592V31.9207C194.548 30.7345 193.719 30.1221 192.369 30.1221H189.615V33.7385H192.422Z" fill="#3F6972"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_50_44" x1="1.76724" y1="20.3211" x2="67.0008" y2="17.0815" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9E5BB"/>
|
||||
<stop offset="0.505423" stop-color="#3F6972"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_50_44" x1="9.2819" y1="42.495" x2="120.454" y2="-7.95169" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#A9E5BB"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_50_44" x1="49.036" y1="19.4377" x2="26.7648" y2="41.3421" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9E5BB"/>
|
||||
<stop offset="1" stop-color="#3F6972"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,7 @@
|
||||
<svg width="67" height="67" viewBox="0 0 67 67" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Folder">
|
||||
<path id="Vector" d="M62.3938 11.1667H31.5458C30.2896 11.1667 29.0333 10.6083 28.1958 9.77083L24.2875 5.58333C23.45 4.60625 22.1938 4.1875 20.9375 4.1875H4.60625C2.09375 4.1875 0 6.28125 0 8.79375V52.6229C0 55.1354 2.09375 57.2292 4.60625 57.2292H62.3938C64.9062 57.2292 67 55.1354 67 52.6229V15.7729C67 13.2604 64.9062 11.1667 62.3938 11.1667Z" fill="#56B3E5"/>
|
||||
<path id="Vector_2" d="M59.8813 15.7729H7.11875C5.16458 15.7729 3.62917 17.3083 3.62917 19.2625V54.2979C3.62917 56.2521 5.16458 57.7875 7.11875 57.7875H60.0208C61.975 57.7875 63.5104 56.2521 63.5104 54.2979V19.2625C63.3708 17.3083 61.8354 15.7729 59.8813 15.7729Z" fill="white"/>
|
||||
<path id="Vector_3" d="M62.3938 21.3563H4.60625C2.09375 21.3563 0 23.45 0 25.9625V58.2063C0 60.7188 2.09375 62.8125 4.60625 62.8125H62.3938C64.9062 62.8125 67 60.7188 67 58.2063V25.9625C67 23.45 64.9062 21.3563 62.3938 21.3563Z" fill="#98D0F1"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1013 B |
@@ -0,0 +1 @@
|
||||
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>
|
||||
|
After Width: | Height: | Size: 963 B |
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 -25 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<path d="M170.2517,56.8186 L192.5047,34.5656 L193.9877,25.1956 C153.4367,-11.6774 88.9757,-7.4964 52.4207,33.9196 C42.2667,45.4226 34.7337,59.7636 30.7167,74.5726 L38.6867,73.4496 L83.1917,66.1106 L86.6277,62.5966 C106.4247,40.8546 139.8977,37.9296 162.7557,56.4286 L170.2517,56.8186 Z" fill="#EA4335">
|
||||
|
||||
</path>
|
||||
<path d="M224.2048,73.9182 C219.0898,55.0822 208.5888,38.1492 193.9878,25.1962 L162.7558,56.4282 C175.9438,67.2042 183.4568,83.4382 183.1348,100.4652 L183.1348,106.0092 C198.4858,106.0092 210.9318,118.4542 210.9318,133.8052 C210.9318,149.1572 198.4858,161.2902 183.1348,161.2902 L127.4638,161.2902 L121.9978,167.2242 L121.9978,200.5642 L127.4638,205.7952 L183.1348,205.7952 C223.0648,206.1062 255.6868,174.3012 255.9978,134.3712 C256.1858,110.1682 244.2528,87.4782 224.2048,73.9182" fill="#4285F4">
|
||||
|
||||
</path>
|
||||
<path d="M71.8704,205.7957 L127.4634,205.7957 L127.4634,161.2897 L71.8704,161.2897 C67.9094,161.2887 64.0734,160.4377 60.4714,158.7917 L52.5844,161.2117 L30.1754,183.4647 L28.2234,191.0387 C40.7904,200.5277 56.1234,205.8637 71.8704,205.7957" fill="#34A853">
|
||||
|
||||
</path>
|
||||
<path d="M71.8704,61.4255 C31.9394,61.6635 -0.2366,94.2275 0.0014,134.1575 C0.1344,156.4555 10.5484,177.4455 28.2234,191.0385 L60.4714,158.7915 C46.4804,152.4705 40.2634,136.0055 46.5844,122.0155 C52.9044,108.0255 69.3704,101.8085 83.3594,108.1285 C89.5244,110.9135 94.4614,115.8515 97.2464,122.0155 L129.4944,89.7685 C115.7734,71.8315 94.4534,61.3445 71.8704,61.4255" fill="#FBBC05">
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg width="26" height="22" viewBox="0 0 26 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.4557 15.0105L18.5202 18.6705L21.3056 21.6632C21.6886 21.4414 22.0064 21.1229 22.227 20.7398L24.8188 16.2655C25.0398 15.8825 25.1559 15.4482 25.1554 15.0063L21.1793 14.2382L17.4557 15.0105Z" fill="#EA4335"/>
|
||||
<path d="M16.7732 0.52609C16.3893 0.305619 15.954 0.189818 15.511 0.190309H10.3358C9.89306 0.191374 9.45813 0.30707 9.07361 0.52609L10.1886 4.2743L12.9108 7.15787L15.6541 4.21974L16.7732 0.52609Z" fill="#188038"/>
|
||||
<path d="M8.39305 15.0109L4.42123 14.1042L0.689211 15.0109C0.688718 15.4528 0.804805 15.8871 1.02581 16.2701L3.6176 20.7444C3.83823 21.1275 4.15601 21.446 4.53903 21.6678L7.28229 18.8472L8.39305 15.0109Z" fill="#1967D2"/>
|
||||
<path d="M21.2592 7.59902L17.6997 1.44574C17.4791 1.06263 17.1613 0.744179 16.7783 0.522339L12.9243 7.17929L17.4557 15.0073H25.1553C25.1558 14.5654 25.0397 14.1311 24.8187 13.7481L21.2592 7.59902Z" fill="#FBBC04"/>
|
||||
<path d="M17.4572 15.0115H8.39431L4.54449 21.6642C4.92842 21.8847 5.36374 22.0005 5.80673 22H20.0448C20.4877 22.0005 20.9231 21.8847 21.307 21.6642L17.4572 15.0115Z" fill="#4285F4"/>
|
||||
<path d="M12.9238 7.17876L9.07393 0.526001C8.69144 0.746682 8.37371 1.06365 8.1525 1.44522L1.02928 13.756C0.808278 14.139 0.692197 14.5732 0.69269 15.0152H8.39232L12.9238 7.17876Z" fill="#34A853"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="14" viewBox="0 0 24 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="Arrow 2" d="M13.0607 0.93934C12.4749 0.353553 11.5251 0.353553 10.9393 0.93934L1.3934 10.4853C0.807611 11.0711 0.807611 12.0208 1.3934 12.6066C1.97919 13.1924 2.92893 13.1924 3.51472 12.6066L12 4.12132L20.4853 12.6066C21.0711 13.1924 22.0208 13.1924 22.6066 12.6066C23.1924 12.0208 23.1924 11.0711 22.6066 10.4853L13.0607 0.93934ZM13.5 3V2H10.5V3H13.5Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 482 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="32" height="19" viewBox="0 0 32 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M28.4148 12.2962C28.4217 12.1931 28.4285 12.0832 28.4285 11.9802C28.4285 9.53491 26.4422 7.54983 23.9953 7.54983C23.1018 7.54983 22.2633 7.81771 21.5691 8.27105C20.7237 6.62941 19.0123 5.50293 17.0396 5.50293C14.2285 5.50293 11.9535 7.7765 11.9535 10.5858C11.9535 10.6889 11.9603 10.7919 11.9672 10.8949C11.8572 10.8881 11.7473 10.8812 11.6304 10.8812C9.38289 10.8812 7.56836 12.7014 7.56836 14.9406C7.56836 17.173 9.37601 18.9864 11.6098 19.0001H11.6373H26.559H29.1983C29.2877 18.9658 29.377 18.9245 29.4595 18.8833C30.6005 18.3064 31.384 17.1249 31.384 15.7512C31.3772 14.0065 30.0919 12.5572 28.4148 12.2962Z" fill="#0069B3"/>
|
||||
<path d="M11.0828 10.0156C11.3715 6.98643 13.9352 4.60296 17.0418 4.60296C18.987 4.60296 20.774 5.53024 21.8943 7.07572C22.5542 6.7941 23.269 6.64299 23.9975 6.64299C24.0456 6.64299 24.0938 6.64299 24.135 6.64299C23.7982 3.3391 21.0077 0.763306 17.6123 0.763306C15.0417 0.763306 12.8217 2.2401 11.7495 4.39689C10.9934 3.8886 10.0793 3.58638 9.1033 3.58638C6.4846 3.58638 4.36078 5.70883 4.36078 8.32584C4.36078 8.67615 4.40202 9.01959 4.47075 9.34929C2.29195 9.50727 0.566772 11.3206 0.566772 13.5461C0.566772 15.8678 2.45003 17.7498 4.77318 17.7498H7.52933C6.97947 16.953 6.65643 15.9845 6.65643 14.9474C6.66331 12.3922 8.60155 10.2834 11.0828 10.0156Z" fill="#0069B3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><path fill="#00bcd4" d="M9,24c0,0-0.258-0.961-0.258-2.289c0-1.593,0.331-3.964,1.258-5.601C4.36,16.847,0,21.658,0,27.5 C0,33.851,5.149,39,11.5,39S40,39,40,39V24H9z"/><path fill="#00bcd4" d="M24 9A15 15 0 1 0 24 39A15 15 0 1 0 24 9Z"/><path fill="#fff" d="M24,36c-6.617,0-12-5.383-12-12s5.383-12,12-12s12,5.383,12,12S30.617,36,24,36z M24,14 c-5.514,0-10,4.486-10,10s4.486,10,10,10s10-4.486,10-10S29.514,14,24,14z"/><path fill="#fff" d="M20.5,31c-0.829,0-1.5-0.672-1.5-1.5v-10c0-0.828,0.671-1.5,1.5-1.5h5c2.481,0,4.5,2.019,4.5,4.5 S27.981,27,25.5,27H22v2.5C22,30.328,21.329,31,20.5,31z M22,24h3.5c0.827,0,1.5-0.673,1.5-1.5S26.327,21,25.5,21H22V24z"/><path fill="#00bcd4" d="M45,22.5c0-3.59-2.91-6.5-6.5-6.5c-0.211,0-0.294-0.02-0.5,0c0.028,0.053-0.002-0.003,0,0 c0.929,1.637,1.258,4.117,1.258,5.711C39.258,23.039,39,24,39,24v4.975C42.355,28.719,45,25.921,45,22.5z"/><path fill="#00bcd4" d="M45.551,25.25C44.665,27.165,42.544,28,41.962,28C40.919,28,39,28,39,28v11c0.317-0.023,0.646,0,1,0 c4.418,0,8-3.582,8-8C48,28.74,47.059,26.703,45.551,25.25z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,18 @@
|
||||
<svg width="32" height="33" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_54_152)">
|
||||
<path d="M7.21044 7.13517C9.03996 7.13517 10.8695 7.14985 12.6985 7.12606C13.2389 7.11949 13.6811 7.28798 14.102 7.59511C14.5447 7.91743 14.992 8.23518 15.4524 8.53119C16.0484 8.91472 16.7087 9.07613 17.4211 9.07411C20.22 9.06652 23.0189 9.07411 25.8199 9.07411C27.3544 9.07411 28.889 9.09181 30.4241 9.06702C31.2994 9.05336 32.0907 9.7076 31.9966 10.6963C31.9045 11.6577 31.8347 12.6266 31.7567 13.592C31.6814 14.5236 31.61 15.4561 31.5336 16.3876C31.4415 17.5124 31.3444 18.6367 31.2523 19.761C31.1759 20.693 31.1036 21.6251 31.0292 22.5571C30.9578 23.4552 30.9002 24.3548 30.8106 25.2515C30.7281 26.0808 30.1296 26.5928 29.2882 26.5938H26.0501C25.3144 26.5938 24.9092 26.2012 24.8945 25.4559C24.8672 24.1089 24.5616 22.8247 23.9266 21.6433C22.4649 18.9206 20.2069 17.2878 17.1307 16.8759C14.5923 16.5359 12.3059 17.2108 10.3398 18.8396C8.37362 20.4684 7.31365 22.5723 7.1391 25.1209C7.12594 25.3142 7.11481 25.5075 7.0966 25.7003C7.05309 26.1637 6.63719 26.5832 6.17323 26.5878C5.00954 26.5999 3.84585 26.607 2.68216 26.5878C1.98243 26.5751 1.42183 25.9679 1.36213 25.2216L0.846562 18.8477C0.710967 17.1683 0.578407 15.4895 0.4418 13.8106C0.300471 12.1071 0.156274 10.4037 0.00921036 8.70018C-0.00921989 8.50025 0.0142399 8.29868 0.0780919 8.10833C0.141944 7.91798 0.244785 7.74304 0.380048 7.59467C0.515311 7.44631 0.680024 7.32778 0.86367 7.24666C1.04732 7.16553 1.24586 7.1236 1.44662 7.12354H7.21449L7.21044 7.13517Z" fill="#C2D3C7"/>
|
||||
<path d="M7.21044 7.13517C9.03996 7.13517 10.8695 7.14985 12.6985 7.12606C13.2389 7.11949 13.6811 7.28798 14.102 7.59511C14.5447 7.91743 14.992 8.23518 15.4524 8.53119C16.0484 8.91472 16.7087 9.07613 17.4211 9.07411C20.22 9.06652 23.0189 9.07411 25.8199 9.07411C27.3544 9.07411 28.889 9.09181 30.4241 9.06702C31.2994 9.05336 32.0907 9.7076 31.9966 10.6963C31.9045 11.6577 31.8347 12.6266 31.7567 13.592C31.6814 14.5236 31.61 15.4561 31.5336 16.3876C31.4415 17.5124 31.3444 18.6367 31.2523 19.761C31.1759 20.693 31.1036 21.6251 31.0292 22.5571C30.9578 23.4552 30.9002 24.3548 30.8106 25.2515C30.7281 26.0808 30.1296 26.5928 29.2882 26.5938H26.0501C25.3144 26.5938 24.9092 26.2012 24.8945 25.4559C24.8672 24.1089 24.5616 22.8247 23.9266 21.6433C22.4649 18.9206 20.2069 17.2878 17.1307 16.8759C14.5923 16.5359 12.3059 17.2108 10.3398 18.8396C8.37362 20.4684 7.31365 22.5723 7.1391 25.1209C7.12594 25.3142 7.11481 25.5075 7.0966 25.7003C7.05309 26.1637 6.63719 26.5832 6.17323 26.5878C5.00954 26.5999 3.84585 26.607 2.68216 26.5878C1.98243 26.5751 1.42183 25.9679 1.36213 25.2216L0.846562 18.8477C0.710967 17.1683 0.578407 15.4895 0.4418 13.8106C0.300471 12.1071 0.156274 10.4037 0.00921036 8.70018C-0.00921989 8.50025 0.0142399 8.29868 0.0780919 8.10833C0.141944 7.91798 0.244785 7.74304 0.380048 7.59467C0.515311 7.44631 0.680024 7.32778 0.86367 7.24666C1.04732 7.16553 1.24586 7.1236 1.44662 7.12354H7.21449L7.21044 7.13517Z" fill="url(#paint0_linear_54_152)"/>
|
||||
<path d="M7.21044 7.13517C9.03996 7.13517 10.8695 7.14985 12.6985 7.12606C13.2389 7.11949 13.6811 7.28798 14.102 7.59511C14.5447 7.91743 14.992 8.23518 15.4524 8.53119C16.0484 8.91472 16.7087 9.07613 17.4211 9.07411C20.22 9.06652 23.0189 9.07411 25.8199 9.07411C27.3544 9.07411 28.889 9.09181 30.4241 9.06702C31.2994 9.05336 32.0907 9.7076 31.9966 10.6963C31.9045 11.6577 31.8347 12.6266 31.7567 13.592C31.6814 14.5236 31.61 15.4561 31.5336 16.3876C31.4415 17.5124 31.3444 18.6367 31.2523 19.761C31.1759 20.693 31.1036 21.6251 31.0292 22.5571C30.9578 23.4552 30.9002 24.3548 30.8106 25.2515C30.7281 26.0808 30.1296 26.5928 29.2882 26.5938H26.0501C25.3144 26.5938 24.9092 26.2012 24.8945 25.4559C24.8672 24.1089 24.5616 22.8247 23.9266 21.6433C22.4649 18.9206 20.2069 17.2878 17.1307 16.8759C14.5923 16.5359 12.3059 17.2108 10.3398 18.8396C8.37362 20.4684 7.31365 22.5723 7.1391 25.1209C7.12594 25.3142 7.11481 25.5075 7.0966 25.7003C7.05309 26.1637 6.63719 26.5832 6.17323 26.5878C5.00954 26.5999 3.84585 26.607 2.68216 26.5878C1.98243 26.5751 1.42183 25.9679 1.36213 25.2216L0.846562 18.8477C0.710967 17.1683 0.578407 15.4895 0.4418 13.8106C0.300471 12.1071 0.156274 10.4037 0.00921036 8.70018C-0.00921989 8.50025 0.0142399 8.29868 0.0780919 8.10833C0.141944 7.91798 0.244785 7.74304 0.380048 7.59467C0.515311 7.44631 0.680024 7.32778 0.86367 7.24666C1.04732 7.16553 1.24586 7.1236 1.44662 7.12354H7.21449L7.21044 7.13517Z" fill="#E17351"/>
|
||||
<path d="M23.1833 25.663C23.1833 29.6445 19.9958 32.853 16.062 32.8672C12.0872 32.8813 8.83243 29.7503 8.82181 25.7277C8.81068 21.613 12.0128 18.5068 15.9967 18.4992C20.1698 18.4916 23.1888 21.8701 23.1833 25.663ZM15.0223 29.2124C15.1107 29.2198 15.1996 29.2064 15.2819 29.1733C15.3642 29.1402 15.4377 29.0883 15.4963 29.0217C15.8647 28.6397 16.2381 28.2627 16.6069 27.8802C17.8303 26.6125 19.053 25.3445 20.2751 24.0762C20.4805 23.8622 20.4774 23.722 20.268 23.513C19.9998 23.2454 19.7231 22.9853 19.4473 22.7252C19.1088 22.4054 19.0223 22.4044 18.7031 22.7358C17.5338 23.9502 16.3625 25.1646 15.2034 26.3865C15.0248 26.5747 14.9201 26.5707 14.7389 26.3971C14.1606 25.8441 13.5661 25.3078 12.9772 24.7658C12.7748 24.5786 12.6352 24.5675 12.4535 24.7557C12.1373 25.0831 11.8348 25.4231 11.5261 25.7571C11.3743 25.923 11.3673 26.0849 11.5362 26.2418C11.7052 26.3987 11.8712 26.5499 12.0381 26.7043C12.8814 27.4801 13.7247 28.256 14.5679 29.0318C14.6964 29.1532 14.8411 29.2251 15.0223 29.2124Z" fill="#3F6972"/>
|
||||
<path d="M23.6022 7.71463C21.5617 7.71463 19.5212 7.70855 17.4802 7.71969C17.057 7.72653 16.6433 7.59349 16.3034 7.34121C15.8526 7.01586 15.3926 6.70063 14.9373 6.38591C14.3637 5.99037 13.683 5.77958 12.9863 5.78176C9.54586 5.74938 6.10538 5.74483 2.6649 5.74938C2.47112 5.74938 2.27734 5.75849 2.08407 5.75394C1.84323 5.74736 1.70662 5.6239 1.70308 5.37596C1.69246 4.6438 1.67981 3.91114 1.67627 3.17847C1.67627 2.85009 1.65704 2.52069 1.69904 2.19332C1.80023 1.40044 2.33907 0.87776 3.1405 0.87776C5.55187 0.865616 7.96357 0.865616 10.3756 0.87776C11.1664 0.880796 11.7822 1.28255 12.3372 1.80675C12.6681 2.11877 13.0071 2.42236 13.3542 2.71752C13.8217 3.11573 14.3661 3.30295 14.9833 3.30295C19.6121 3.30058 24.2411 3.29957 28.8702 3.29991C29.5538 3.29991 30.0567 3.57314 30.3501 4.19905C30.4316 4.38532 30.4708 4.58732 30.465 4.79054C30.465 5.59152 30.465 6.39249 30.465 7.19346C30.465 7.59319 30.3355 7.71716 29.9272 7.71716C27.8187 7.71682 25.7104 7.71598 23.6022 7.71463Z" fill="#3F6972"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_54_152" x1="-2.52998" y1="13.9432" x2="49.7853" y2="7.59802" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9E5BB"/>
|
||||
<stop offset="1" stop-color="#3F6972"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_54_152">
|
||||
<rect width="32.002" height="32" fill="white" transform="translate(0 0.867676)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 461 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="5" height="7" viewBox="0 0 5 7" fill="none">
|
||||
<path d="M4.30067 3.68763C4.30091 3.7877 4.25904 3.88468 4.18232 3.96173L1.60953 6.53135C1.52219 6.61881 1.39669 6.67381 1.26062 6.68425C1.12456 6.69469 0.989087 6.65972 0.884005 6.58703C0.778924 6.51433 0.712842 6.40987 0.700297 6.29663C0.687753 6.18338 0.729772 6.07063 0.817113 5.98317L3.12233 3.68763L0.899442 1.3921C0.8567 1.3483 0.824781 1.29789 0.80552 1.24378C0.786259 1.18968 0.780036 1.13293 0.787209 1.07682C0.794381 1.0207 0.814808 0.966321 0.847314 0.916797C0.879821 0.867273 0.923767 0.823585 0.976626 0.788242C1.02953 0.749022 1.0916 0.719317 1.15894 0.70099C1.22629 0.682663 1.29745 0.676109 1.36798 0.681738C1.4385 0.687367 1.50688 0.705057 1.56881 0.733701C1.63074 0.762345 1.68489 0.801326 1.72788 0.848201L4.2132 3.41782C4.27778 3.49709 4.30858 3.59209 4.30067 3.68763Z" fill="#FEFFFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 908 B |
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="15" viewBox="0 0 14 15" fill="none">
|
||||
<circle cx="6.49041" cy="6.9262" r="4.01653" stroke="#B5B5B5" stroke-width="1.14758"/>
|
||||
<path d="M11.6545 12.0903L9.93311 10.369" stroke="#B5B5B5" stroke-width="1.14758" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 304 B |
|
After Width: | Height: | Size: 86 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg width="31" height="32" viewBox="0 0 31 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.9133 0.921143C10.2536 0.921143 8.89751 2.27724 8.89751 3.93693C8.89751 5.59663 10.2536 6.95272 11.9133 6.95272H14.9291V3.93693C14.9291 2.27724 13.5932 0.921143 11.9133 0.921143ZM11.9133 8.95651H3.89818C2.23848 8.95651 0.882385 10.3126 0.882385 11.9723C0.882385 13.632 2.23848 14.9881 3.89818 14.9881H11.9335C13.5932 14.9881 14.9493 13.632 14.9493 11.9723C14.9291 10.3126 13.5932 8.95651 11.9133 8.95651Z" fill="#36C5F0"/>
|
||||
<path d="M31 11.9722C31 10.3125 29.6439 8.95637 27.9842 8.95637C26.3245 8.95637 24.9684 10.3125 24.9684 11.9722V14.9879H27.9842C29.6439 15.0082 31 13.6521 31 11.9722ZM22.9646 11.9722V3.91655C22.9646 2.25685 21.6085 0.900757 19.9488 0.900757C18.2891 0.900757 16.933 2.25685 16.933 3.91655V11.9722C16.933 13.6319 18.2891 14.9879 19.9488 14.9879C21.6288 15.0082 22.9646 13.6521 22.9646 11.9722Z" fill="#2EB67D"/>
|
||||
<path d="M19.9488 31.0993C21.6085 31.0993 22.9646 29.7432 22.9646 28.0835C22.9646 26.4238 21.6085 25.0677 19.9488 25.0677H16.933V28.0835C16.933 29.7432 18.2891 31.0993 19.9488 31.0993ZM19.9488 23.0437H27.9842C29.6439 23.0437 31 21.6876 31 20.0279C31 18.3682 29.6439 17.0121 27.9842 17.0121H19.9488C18.2891 17.0121 16.933 18.3682 16.933 20.0279C16.933 21.6876 18.2891 23.0437 19.9488 23.0437Z" fill="#ECB22E"/>
|
||||
<path d="M0.882385 20.0279C0.882385 21.6876 2.23848 23.0437 3.89818 23.0437C5.55787 23.0437 6.91397 21.6876 6.91397 20.0279V17.0121H3.89818C2.21824 17.0121 0.882385 18.3682 0.882385 20.0279ZM8.91775 20.0279V28.0835C8.91775 29.7432 10.2738 31.0993 11.9335 31.0993C13.5932 31.0993 14.9493 29.7432 14.9493 28.0835V20.0279C14.9493 18.3682 13.5932 17.0121 11.9335 17.0121C10.2536 17.0121 8.91775 18.3682 8.91775 20.0279Z" fill="#E01E5A"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,220 @@
|
||||
(function ($) {
|
||||
$('.file-manager-advanced-select2.fma-code-editor-theme').select2({
|
||||
templateResult: function (a, b) {
|
||||
return disable_pro_themes(a, b, 'https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=code_editor_pro_theme&utm_campaign=plugin');
|
||||
}
|
||||
});
|
||||
|
||||
$('.file-manager-advanced-select2.fma-theme').select2({
|
||||
templateResult: function (a, b) {
|
||||
return disable_pro_themes(a, b, 'https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=file_manager_pro_theme&utm_campaign=plugin');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '.on-click-show-popup', function () {
|
||||
file_manager_advanced_popup($(this).attr('fma-href'));
|
||||
});
|
||||
|
||||
$('#fma__hide-banner').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$('.afm__right-side').hide();
|
||||
$('.afm__left-side').css({ 'width': '100%', 'max-width': '100%' });
|
||||
|
||||
rest_api_post('hide-banner')
|
||||
.catch(error => console.error('Error:', error));
|
||||
});
|
||||
|
||||
$('#fma__minimize-maximize').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$(this).children().toggleClass('fma__minimized');
|
||||
|
||||
var action = 'maximize';
|
||||
if ('true' === $(this).attr('fma-maximized')) {
|
||||
action = 'minimize';
|
||||
}
|
||||
|
||||
minimize_maximize(this, action);
|
||||
|
||||
rest_api_post(
|
||||
'minimize-maximize-banner',
|
||||
{ action: action }
|
||||
).catch(error => console.error('Error:', error));
|
||||
});
|
||||
|
||||
$('.dropbox__wrap, .file-logs__wrap, .fma__wrap').on('click', function () {
|
||||
|
||||
var redirect_url = $(this).attr('afmp-href');
|
||||
if (!redirect_url) {
|
||||
redirect_url = '';
|
||||
}
|
||||
|
||||
file_manager_advanced_popup(redirect_url, '', '');
|
||||
});
|
||||
|
||||
$('.googledrive__wrap').on('click', function () {
|
||||
file_manager_advanced_popup(
|
||||
'https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=google_drive_banner&utm_campaign=plugin',
|
||||
'',
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
$('.dropbox__wrap, .onedrive__wrap').on('click', function () {
|
||||
file_manager_advanced_popup('', '', '');
|
||||
});
|
||||
|
||||
// Use event delegation for blocks wrap (since it's added dynamically)
|
||||
// Same behavior as OneDrive/Dropbox - empty string for default popup
|
||||
$(document).on('click', '.fma__blocks__wrap', function () {
|
||||
var redirect_url = $(this).attr('afmp-href');
|
||||
if (!redirect_url) {
|
||||
redirect_url = 'https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=blocks_banner&utm_campaign=plugin';
|
||||
}
|
||||
file_manager_advanced_popup(redirect_url, '', '');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.aws__wrap').on('click', function () {
|
||||
file_manager_advanced_popup('https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=aws_banner&utm_campaign=plugin', '', '');
|
||||
});
|
||||
|
||||
$('.github__wrap').on('click', function () {
|
||||
file_manager_advanced_popup(
|
||||
'https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=github_banner&utm_campaign=plugin',
|
||||
'',
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
$('.googlecloud__wrap').on('click', function () {
|
||||
file_manager_advanced_popup(
|
||||
'https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=googlecloud_banner&utm_campaign=plugin',
|
||||
'',
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
function file_manager_advanced_popup(redirect_url = '', message = '', button_title = '') {
|
||||
if (!redirect_url.length) {
|
||||
redirect_url = 'https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=dropbox_banner&utm_campaign=plugin';
|
||||
}
|
||||
|
||||
if (!message.length) {
|
||||
message = 'Get advanced features with Advanced File Manager Pro!';
|
||||
}
|
||||
|
||||
if (!button_title.length) {
|
||||
button_title = 'Get Pro Now';
|
||||
}
|
||||
var element = $('#fma__pro_popup');
|
||||
if (element.length) {
|
||||
element.show();
|
||||
} else {
|
||||
let fma__pro_popup = `<div class="fma__pro-popup" id="fma__pro_popup">
|
||||
<div class="fma__pro-popup-wrapper">
|
||||
|
||||
<div class="fma__pro-close-button">
|
||||
<a id="close-popup-btn" href="#">
|
||||
<img src="${afmAdmin.assetsURL}images/close-popup.svg" alt="">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="fma__pro-popup-content">
|
||||
|
||||
<div>
|
||||
<img src="${afmAdmin.assetsURL}images/fma-logo.svg" alt="">
|
||||
</div>
|
||||
|
||||
<div class="afmp__pro-popup-desc">
|
||||
<p>
|
||||
${message}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="fma__pro-popup-cta">
|
||||
<a target="_blank" href="${redirect_url}">
|
||||
<img style="width: 20px;margin-bottom: -3px;" src="${afmAdmin.assetsURL}images/crown.svg" alt="">
|
||||
${button_title}
|
||||
<img style="width: 10px;margin-bottom: -2px;" src="${afmAdmin.assetsURL}images/right-arrow.svg" alt="">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>`;
|
||||
$('body').append(fma__pro_popup);
|
||||
}
|
||||
|
||||
$(document).on('click', '#close-popup-btn', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$('#fma__pro_popup').remove();
|
||||
});
|
||||
}
|
||||
|
||||
function minimize_maximize(element, action) {
|
||||
switch (action) {
|
||||
case 'maximize':
|
||||
$('#remove-on-minimize, .fma__footer').show();
|
||||
$(element).attr('fma-maximized', 'true');
|
||||
break;
|
||||
case 'minimize':
|
||||
$('#remove-on-minimize, .fma__footer').hide();
|
||||
$(element).attr('fma-maximized', 'false');
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var rest_api_post = async function (url, params = {}) {
|
||||
url = afmAdmin.jsonURL + 'file-manager-advanced/v1/' + url;
|
||||
|
||||
return await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(params)
|
||||
}).then(response => response.json());
|
||||
};
|
||||
|
||||
var disable_pro_themes = function (a, b, redirect_url) {
|
||||
if (a.id === '') {
|
||||
return a.text;
|
||||
}
|
||||
|
||||
if (!a.disabled) {
|
||||
return a.text;
|
||||
}
|
||||
|
||||
return $(`<span fma-href="${redirect_url}" class="fma__clearfix on-click-show-popup">
|
||||
<span class="fma__left">
|
||||
${a.text}
|
||||
</span>
|
||||
<span style="font-size: 15px;" class="fma__right">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
|
||||
<path d="M11.341 11.0011H2.6642C2.57543 11.0011 2.49029 11.0364 2.42752 11.0992C2.36475 11.1619 2.32948 11.2471 2.32948 11.3358V12.0001C2.32948 12.0889 2.36475 12.174 2.42752 12.2368C2.49029 12.2996 2.57543 12.3348 2.6642 12.3348H11.341C11.4289 12.3348 11.5132 12.3003 11.5759 12.2386C11.6385 12.177 11.6743 12.0931 11.6757 12.0053V11.3358C11.6744 11.2475 11.6387 11.1631 11.5762 11.1006C11.5137 11.0381 11.4293 11.0024 11.341 11.0011ZM12.6747 4.30687C12.4015 4.30687 12.1396 4.41537 11.9464 4.60851C11.7533 4.80165 11.6448 5.06361 11.6448 5.33675C11.6469 5.479 11.6785 5.61926 11.7375 5.7487L10.2287 6.655C10.1524 6.70023 10.068 6.72985 9.98016 6.74216C9.89236 6.75447 9.80299 6.74921 9.71723 6.72669C9.63148 6.70418 9.55105 6.66485 9.48062 6.611C9.41019 6.55714 9.35116 6.48984 9.30696 6.41298L7.60765 3.43661C7.77678 3.3047 7.90051 3.12327 7.96156 2.91764C8.0226 2.71202 8.01793 2.49247 7.94818 2.28963C7.87844 2.08679 7.7471 1.91079 7.5725 1.7862C7.3979 1.66161 7.18876 1.59464 6.97427 1.59464C6.75977 1.59464 6.55063 1.66161 6.37603 1.7862C6.20144 1.91079 6.0701 2.08679 6.00035 2.28963C5.9306 2.49247 5.92593 2.71202 5.98698 2.91764C6.04803 3.12327 6.17175 3.3047 6.34089 3.43661L4.64158 6.41298C4.59737 6.48984 4.53834 6.55714 4.46791 6.611C4.39748 6.66485 4.31705 6.70418 4.2313 6.72669C4.14555 6.74921 4.05618 6.75447 3.96837 6.74216C3.88057 6.72985 3.79609 6.70023 3.71983 6.655L2.21105 5.7487C2.27125 5.61966 2.30287 5.47914 2.30374 5.33675C2.30464 5.13643 2.24559 4.94041 2.13421 4.77391C2.02282 4.60741 1.86417 4.47803 1.67867 4.4024C1.49316 4.32678 1.28928 4.30837 1.09323 4.34955C0.897177 4.39072 0.717924 4.48959 0.578513 4.63345C0.439103 4.77731 0.345909 4.95958 0.310913 5.15683C0.275917 5.35408 0.300718 5.55728 0.382129 5.74032C0.46354 5.92336 0.597838 6.07786 0.767757 6.18397C0.937676 6.29007 1.13545 6.34293 1.33565 6.33574C1.39044 6.34108 1.44563 6.34108 1.50043 6.33574L3.00921 10.3574H11.0063L12.5099 6.33574H12.6747C12.9279 6.31757 13.1648 6.20416 13.3378 6.01833C13.5108 5.8325 13.607 5.58805 13.607 5.33418C13.607 5.0803 13.5108 4.83585 13.3378 4.65002C13.1648 4.46419 12.9279 4.35078 12.6747 4.33261V4.30687Z" fill="#FFCA38"/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>` );
|
||||
}
|
||||
|
||||
// Fix for notices appearing inside the banner - run immediately and on load
|
||||
function fixAdminNotices() {
|
||||
var $notices = $('.afm__right-side .notice, .afm__right-side .updated, .afm__right-side .error, .afm__right-side .is-dismissible');
|
||||
if ($notices.length > 0) {
|
||||
$notices.insertBefore('.afm__left-side');
|
||||
$notices.css('margin-left', '0').css('margin-right', '0').css('margin-bottom', '20px').show();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
fixAdminNotices();
|
||||
// Check again after a short delay in case of dynamic insertions
|
||||
setTimeout(fixAdminNotices, 500);
|
||||
setTimeout(fixAdminNotices, 2000);
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,652 @@
|
||||
jQuery(document).ready(function () {
|
||||
// Check if debug feature is enabled
|
||||
var debugEnabled = afm_object && afm_object.debug_enabled === '1';
|
||||
|
||||
// Global variables for error tracking
|
||||
var hasErrors = false;
|
||||
var currentEditor = null;
|
||||
var currentErrors = [];
|
||||
var lastButtonState = null;
|
||||
var tooltipTimeout = null;
|
||||
var lastTooltipLine = null;
|
||||
var isSaveButtonClicked = false;
|
||||
|
||||
// CSS styles for error highlighting
|
||||
var errorStyles = `
|
||||
<style>
|
||||
.fma-error-line {
|
||||
background-color: #fed7d7 !important;
|
||||
border-left: 3px solid #c53030 !important;
|
||||
}
|
||||
.fma-error-underline {
|
||||
text-decoration: underline wavy #c53030 !important;
|
||||
text-decoration-thickness: 2px !important;
|
||||
}
|
||||
.fma-error-marker {
|
||||
color: #c53030 !important;
|
||||
font-size: 14px !important;
|
||||
font-weight: bold !important;
|
||||
text-align: center !important;
|
||||
line-height: 1 !important;
|
||||
}
|
||||
.fma-error-gutter {
|
||||
background-color: #fed7d7 !important;
|
||||
border-right: 2px solid #c53030 !important;
|
||||
}
|
||||
.fma-save-close-disabled {
|
||||
opacity: 0.5 !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
.fma-error-tooltip {
|
||||
position: absolute;
|
||||
background: #2d3748;
|
||||
color: white;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
font-family: 'Courier New', monospace;
|
||||
z-index: 10000;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
||||
max-width: 300px;
|
||||
word-wrap: break-word;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.fma-error-tooltip::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-bottom: 5px solid #2d3748;
|
||||
}
|
||||
.fma-error-tooltip .error-title {
|
||||
font-weight: bold;
|
||||
color: #feb2b2;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.fma-error-tooltip .error-message {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
.fma-error-tooltip .error-line {
|
||||
color: #a0aec0;
|
||||
font-size: 11px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
jQuery('head').append(errorStyles);
|
||||
|
||||
if (1 == afm_object.hide_path) {
|
||||
var custom_css = `<style id="hide-path" type="text/css">.elfinder-info-path { display:none; } .elfinder-info-tb tr:nth-child(2) { display:none; }</style>`;
|
||||
jQuery("head").append(custom_css);
|
||||
}
|
||||
|
||||
var hide_preferences_css = `<style id="hide-preferences" type="text/css">
|
||||
.elfinder-contextmenu-item:has( .elfinder-button-icon.elfinder-button-icon-preference.elfinder-contextmenu-icon ) {display: none;}
|
||||
.elfinder-button-icon-replace {
|
||||
background-image: url(${afm_object.plugin_url}application/assets/images/replace.png);
|
||||
background-size: 16px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
.elfinder-contextmenu-icon-replace {
|
||||
background-image: url(${afm_object.plugin_url}application/assets/images/replace.png);
|
||||
background-size: 16px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
</style>`;
|
||||
jQuery('head').append(hide_preferences_css);
|
||||
|
||||
var fmakey = afm_object.nonce;
|
||||
var fma_locale = afm_object.locale;
|
||||
var fma_cm_theme = afm_object.cm_theme;
|
||||
|
||||
// PHP Debug Analysis function
|
||||
function analyzePHPDebug(code, filename, callback) {
|
||||
jQuery.ajax({
|
||||
url: afm_object.ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'fma_debug_php',
|
||||
nonce: fmakey,
|
||||
php_code: code,
|
||||
filename: filename
|
||||
},
|
||||
success: function (response) {
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback(response);
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback({
|
||||
valid: false,
|
||||
debug_info: {},
|
||||
message: 'Failed to analyze PHP code'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Highlight error lines in CodeMirror
|
||||
function highlightErrorLines(editor, errors) {
|
||||
if (!editor || !errors || errors.length === 0) {
|
||||
clearErrorHighlights(editor);
|
||||
return;
|
||||
}
|
||||
|
||||
currentErrors = errors;
|
||||
|
||||
for (var i = 0; i < editor.lineCount(); i++) {
|
||||
editor.removeLineClass(i, 'background', 'fma-error-line');
|
||||
editor.removeLineClass(i, 'text', 'fma-error-underline');
|
||||
editor.setGutterMarker(i, 'fma-error-gutter', null);
|
||||
}
|
||||
|
||||
errors.forEach(function (error) {
|
||||
if (error.line && error.line > 0) {
|
||||
var lineNumber = error.line - 1;
|
||||
editor.addLineClass(lineNumber, 'background', 'fma-error-line');
|
||||
editor.addLineClass(lineNumber, 'text', 'fma-error-underline');
|
||||
|
||||
var marker = document.createElement('div');
|
||||
marker.className = 'fma-error-marker';
|
||||
marker.innerHTML = '⚠️';
|
||||
marker.title = error.message;
|
||||
editor.setGutterMarker(lineNumber, 'fma-error-gutter', marker);
|
||||
|
||||
// Markers have titles which browser handles, but for the line text we use tooltips
|
||||
}
|
||||
});
|
||||
|
||||
hasErrors = true;
|
||||
updateSaveCloseButton();
|
||||
}
|
||||
|
||||
// Clear error highlights
|
||||
function clearErrorHighlights(editor) {
|
||||
if (!editor) return;
|
||||
|
||||
for (var i = 0; i < editor.lineCount(); i++) {
|
||||
editor.removeLineClass(i, 'background', 'fma-error-line');
|
||||
editor.removeLineClass(i, 'text', 'fma-error-underline');
|
||||
editor.setGutterMarker(i, 'fma-error-gutter', null);
|
||||
}
|
||||
|
||||
hideErrorTooltip();
|
||||
currentErrors = [];
|
||||
hasErrors = false;
|
||||
updateSaveCloseButton();
|
||||
}
|
||||
|
||||
// Show error tooltip on hover
|
||||
function showErrorTooltip(event, error) {
|
||||
if (tooltipTimeout) clearTimeout(tooltipTimeout);
|
||||
|
||||
if (lastTooltipLine === error.line) {
|
||||
// Just update position if moving within same line
|
||||
var tooltip = jQuery('.fma-error-tooltip');
|
||||
if (tooltip.length) {
|
||||
var x = event.pageX + 10;
|
||||
var y = event.pageY - 15;
|
||||
tooltip.css({ left: x + 'px', top: (y - tooltip.outerHeight()) + 'px' });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
tooltipTimeout = setTimeout(function () {
|
||||
jQuery('.fma-error-tooltip').remove();
|
||||
var tooltipHtml = `
|
||||
<div class="fma-error-tooltip">
|
||||
<div class="error-title">⚠️ PHP Error</div>
|
||||
<div class="error-message">${error.message}</div>
|
||||
<div class="error-line">Line ${error.line}</div>
|
||||
</div>
|
||||
`;
|
||||
var tooltip = jQuery(tooltipHtml).appendTo('body');
|
||||
var x = event.pageX + 10;
|
||||
var y = event.pageY - 15;
|
||||
tooltip.css({ left: x + 'px', top: (y - tooltip.outerHeight()) + 'px' });
|
||||
lastTooltipLine = error.line;
|
||||
}, 50); // Faster response
|
||||
}
|
||||
|
||||
// Hide error tooltip
|
||||
function hideErrorTooltip() {
|
||||
if (tooltipTimeout) clearTimeout(tooltipTimeout);
|
||||
jQuery('.fma-error-tooltip').remove();
|
||||
lastTooltipLine = null;
|
||||
}
|
||||
|
||||
// Get error for specific line number
|
||||
function getErrorForLine(lineNumber) {
|
||||
for (var i = 0; i < currentErrors.length; i++) {
|
||||
if (currentErrors[i].line === lineNumber + 1) return currentErrors[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Update Save & Close button state
|
||||
function updateSaveCloseButton() {
|
||||
var currentState = hasErrors ? 'disabled' : 'enabled';
|
||||
if (lastButtonState === currentState) return;
|
||||
lastButtonState = currentState;
|
||||
|
||||
var selectors = [
|
||||
'.elfinder-button-save-close', '.elfinder-button-save',
|
||||
'[title*="Save"]', '[title*="save"]',
|
||||
'button[title*="Save"]', 'button[title*="save"]',
|
||||
'button:contains("Save")', 'button:contains("save")'
|
||||
];
|
||||
var saveCloseBtn = jQuery(selectors.join(', ')).filter(':visible');
|
||||
|
||||
if (saveCloseBtn.length > 0) {
|
||||
if (hasErrors) {
|
||||
saveCloseBtn.addClass('fma-save-close-disabled').attr('disabled', 'disabled');
|
||||
saveCloseBtn.css({ opacity: '0.5', cursor: 'not-allowed' });
|
||||
saveCloseBtn.off('click.fma-disable').on('click.fma-disable', function (e) {
|
||||
e.preventDefault(); return false;
|
||||
});
|
||||
} else {
|
||||
saveCloseBtn.removeClass('fma-save-close-disabled').removeAttr('disabled');
|
||||
saveCloseBtn.css({ opacity: '1', cursor: 'pointer' });
|
||||
saveCloseBtn.off('click.fma-disable');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Periodic check for Save button
|
||||
setInterval(function () {
|
||||
if (currentEditor && hasErrors) updateSaveCloseButton();
|
||||
}, 5000);
|
||||
|
||||
// Show error popup on save
|
||||
function showErrorSavePopup(errors, callback) {
|
||||
var errorList = errors.map(function (error) {
|
||||
return `Line ${error.line}: ${error.message}`;
|
||||
}).join('<br>');
|
||||
|
||||
var popupHtml = `
|
||||
<div class="fma-modal-overlay" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 10000; display: flex; justify-content: center; align-items: center;">
|
||||
<div class="fma-error-popup" style="background: white; border-radius: 8px; padding: 20px; max-width: 500px; width: 90%; box-shadow: 0 4px 20px rgba(0,0,0,0.3);">
|
||||
<h3 style="color: #c53030;">PHP Syntax Errors Found</h3>
|
||||
<div style="background: #fed7d7; padding: 10px; border-radius: 4px; font-family: monospace;">${errorList}</div>
|
||||
<div style="margin-top: 15px; display: flex; gap: 10px; justify-content: flex-end;">
|
||||
<button class="fma-error-okay" style="padding: 8px 15px;">Okay</button>
|
||||
<button class="fma-error-save-anyway" style="padding: 8px 15px; background: #c53030; color: white; border: none;">Save Anyway</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
jQuery('.fma-modal-overlay').remove();
|
||||
var popup = jQuery(popupHtml).appendTo('body');
|
||||
|
||||
popup.find('.fma-error-okay').on('click', function () {
|
||||
popup.remove();
|
||||
if (callback) callback(false);
|
||||
});
|
||||
|
||||
popup.find('.fma-error-save-anyway').on('click', function () {
|
||||
popup.remove();
|
||||
if (callback) callback(true);
|
||||
});
|
||||
}
|
||||
|
||||
// Success Modal
|
||||
function showSuccessModal(message) {
|
||||
if (jQuery('.fma-modal-overlay').length > 0) return;
|
||||
var modalHtml = `
|
||||
<div class="fma-modal-overlay" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 10001; display: flex; align-items: center; justify-content: center;">
|
||||
<div style="background: white; padding: 30px; border-radius: 8px; text-align: center;">
|
||||
<div style="color: #46b450; font-size: 40px;">✓</div>
|
||||
<p>${message}</p>
|
||||
<button class="fma-modal-close">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
var modal = jQuery(modalHtml).appendTo('body');
|
||||
modal.find('.fma-modal-close').on('click', function () { modal.remove(); });
|
||||
setTimeout(function () { modal.remove(); }, 3000);
|
||||
}
|
||||
|
||||
// Initialize elFinder
|
||||
var elfinder_object = jQuery('#file_manager_advanced').elfinder({
|
||||
cssAutoLoad: false,
|
||||
url: afm_object.ajaxurl,
|
||||
customData: {
|
||||
action: 'fma_load_fma_ui',
|
||||
_fmakey: fmakey,
|
||||
},
|
||||
defaultView: 'list',
|
||||
height: 500,
|
||||
lang: fma_locale,
|
||||
ui: afm_object.ui,
|
||||
commandsOptions: {
|
||||
edit: {
|
||||
mimes: [],
|
||||
editors: [{
|
||||
mimes: ['text/plain', 'text/html', 'text/javascript', 'text/css', 'text/x-php', 'application/x-php'],
|
||||
info: { name: 'Code Editor' },
|
||||
load: function (textarea) {
|
||||
var mimeType = this.file.mime;
|
||||
var filename = this.file.name;
|
||||
var self = this;
|
||||
|
||||
var editor = CodeMirror.fromTextArea(textarea, {
|
||||
mode: mimeType,
|
||||
indentUnit: 4,
|
||||
lineNumbers: true,
|
||||
theme: fma_cm_theme,
|
||||
gutters: ["CodeMirror-lint-markers", "CodeMirror-linenumbers"]
|
||||
});
|
||||
|
||||
editor.fma_file_info = { filename: filename, mime: mimeType, hash: self.file.hash };
|
||||
|
||||
if (debugEnabled && filename.toLowerCase().endsWith('.php')) {
|
||||
editor.on('change', function () {
|
||||
var code = editor.getValue();
|
||||
analyzePHPDebug(code, filename, function (result) {
|
||||
if (result.valid) {
|
||||
clearErrorHighlights(editor);
|
||||
} else {
|
||||
highlightErrorLines(editor, result.errors);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Hover tooltip: CodeMirror coordsChar() "page" mode needs document coords (pageX/pageY)
|
||||
var wrapper = editor.getWrapperElement();
|
||||
jQuery(wrapper).on('mousemove.fma-debug', function (e) {
|
||||
if (!hasErrors || currentErrors.length === 0) return;
|
||||
|
||||
var docLeft = e.pageX != null ? e.pageX : (e.clientX + (window.scrollX || document.documentElement.scrollLeft || 0));
|
||||
var docTop = e.pageY != null ? e.pageY : (e.clientY + (window.scrollY || document.documentElement.scrollTop || 0));
|
||||
var coords = editor.coordsChar({ left: docLeft, top: docTop }, 'page');
|
||||
if (coords.outside) return;
|
||||
var error = getErrorForLine(coords.line);
|
||||
|
||||
if (error) {
|
||||
showErrorTooltip(e, error);
|
||||
} else {
|
||||
hideErrorTooltip();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery(wrapper).on('mouseleave.fma-debug', function () {
|
||||
hideErrorTooltip();
|
||||
});
|
||||
|
||||
currentEditor = editor;
|
||||
return editor;
|
||||
},
|
||||
close: function (textarea, instance) {
|
||||
if (instance) clearErrorHighlights(instance);
|
||||
currentEditor = null;
|
||||
},
|
||||
save: function (textarea, editor) {
|
||||
var code = editor.getValue();
|
||||
var filename = editor.fma_file_info ? editor.fma_file_info.filename : 'unknown.php';
|
||||
|
||||
if (filename.toLowerCase().endsWith('.php') && hasErrors) {
|
||||
analyzePHPDebug(code, filename, function (result) {
|
||||
if (!result.valid && result.errors) {
|
||||
showErrorSavePopup(result.errors, function (saveAnyway) {
|
||||
if (saveAnyway) {
|
||||
jQuery(textarea).val(code);
|
||||
if (typeof editor.save === 'function') editor.save();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
jQuery(textarea).val(code);
|
||||
return true;
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
workerBaseUrl: afm_object.plugin_url + 'application/library/js/worker/',
|
||||
});
|
||||
|
||||
// Override search command to add contentTag parameter for content search (after init)
|
||||
function applyContentSearchOverride(fm) {
|
||||
if (!fm || !fm._commands || !fm._commands.search) return;
|
||||
if (fm._commands.search._fmaContentSearchPatched) return;
|
||||
fm._commands.search._fmaContentSearchPatched = true;
|
||||
var originalSearchExec = fm._commands.search.exec;
|
||||
|
||||
// Override exec method to add contentTag for SearchTag type
|
||||
fm._commands.search.exec = function(q, target, mime, type) {
|
||||
var self = this;
|
||||
var sType = type || '';
|
||||
|
||||
// If SearchTag type, we need to send contentTag parameter
|
||||
if (sType === 'SearchTag' && q) {
|
||||
var contentTag = q; // Store the tag
|
||||
var fm = this.fm;
|
||||
var reqDef = [];
|
||||
var onlyMimes = fm.options.onlyMimes;
|
||||
var phash, targetVolids = [];
|
||||
|
||||
// Custom setType function that encodes tag in q parameter for SearchTag
|
||||
var setType = function(data) {
|
||||
if (sType && sType !== 'SearchName' && sType !== 'SearchMime') {
|
||||
data.type = sType;
|
||||
}
|
||||
if (sType === 'SearchTag') {
|
||||
data.q = '__CONTENT_SEARCH__:' + contentTag;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
var rootCnt;
|
||||
|
||||
// Process target
|
||||
if (typeof target == 'object') {
|
||||
mime = target.mime || '';
|
||||
target = target.target || '';
|
||||
}
|
||||
target = target ? target : '';
|
||||
|
||||
// Process mimes
|
||||
if (mime) {
|
||||
mime = jQuery.trim(mime).replace(',', ' ').split(' ');
|
||||
if (onlyMimes.length) {
|
||||
mime = jQuery.map(mime, function(m) {
|
||||
m = jQuery.trim(m);
|
||||
return m && (jQuery.inArray(m, onlyMimes) !== -1
|
||||
|| jQuery.grep(onlyMimes, function(om) { return m.indexOf(om) === 0 ? true : false; }).length
|
||||
) ? m : null;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
mime = [].concat(onlyMimes);
|
||||
}
|
||||
|
||||
fm.trigger('searchstart', setType({query: '', target: target, mimes: mime}));
|
||||
|
||||
if (!onlyMimes.length || mime.length) {
|
||||
if (target === '' && fm.api >= 2.1) {
|
||||
rootCnt = Object.keys(fm.roots).length;
|
||||
jQuery.each(fm.roots, function(id, hash) {
|
||||
reqDef.push(fm.request({
|
||||
data: setType({cmd: 'search', target: hash, mimes: mime}),
|
||||
notify: {type: 'search', cnt: 1, hideCnt: (rootCnt > 1 ? false : true)},
|
||||
cancel: true,
|
||||
preventDone: true
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
reqDef.push(fm.request({
|
||||
data: setType({cmd: 'search', target: target, mimes: mime}),
|
||||
notify: {type: 'search', cnt: 1, hideCnt: true},
|
||||
cancel: true,
|
||||
preventDone: true
|
||||
}));
|
||||
if (target !== '' && fm.api >= 2.1 && Object.keys(fm.leafRoots).length) {
|
||||
jQuery.each(fm.leafRoots, function(hash, roots) {
|
||||
phash = hash;
|
||||
while (phash) {
|
||||
if (target === phash) {
|
||||
jQuery.each(roots, function() {
|
||||
var f = fm.file(this);
|
||||
f && f.volumeid && targetVolids.push(f.volumeid);
|
||||
reqDef.push(fm.request({
|
||||
data: setType({cmd: 'search', target: this, mimes: mime}),
|
||||
notify: {type: 'search', cnt: 1, hideCnt: false},
|
||||
cancel: true,
|
||||
preventDone: true
|
||||
}));
|
||||
});
|
||||
}
|
||||
phash = (fm.file(phash) || {}).phash;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reqDef = [jQuery.Deferred().resolve({files: []})];
|
||||
}
|
||||
|
||||
fm.searchStatus.mixed = (reqDef.length > 1) ? targetVolids : false;
|
||||
|
||||
return jQuery.when.apply(jQuery, reqDef).done(function(data) {
|
||||
var argLen = arguments.length, i;
|
||||
data.warning && fm.error(data.warning);
|
||||
if (argLen > 1) {
|
||||
data.files = (data.files || []);
|
||||
for (i = 1; i < argLen; i++) {
|
||||
arguments[i].warning && fm.error(arguments[i].warning);
|
||||
if (arguments[i].files) {
|
||||
data.files.push.apply(data.files, arguments[i].files);
|
||||
}
|
||||
}
|
||||
}
|
||||
data.files && data.files.length && fm.cache(data.files);
|
||||
fm.lazy(function() {
|
||||
fm.trigger('search', data);
|
||||
}).then(function() {
|
||||
return fm.lazy(function() {
|
||||
fm.trigger('searchdone');
|
||||
});
|
||||
}).then(function() {
|
||||
data.sync && fm.sync();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return originalSearchExec.call(self, q, target, mime, type);
|
||||
}
|
||||
};
|
||||
}
|
||||
if (elfinder_object && elfinder_object.length) {
|
||||
var fm = elfinder_object.elfinder('instance');
|
||||
if (fm) {
|
||||
fm.one('init', function() { applyContentSearchOverride(fm); });
|
||||
applyContentSearchOverride(fm);
|
||||
}
|
||||
}
|
||||
|
||||
// When user clears search and presses Enter (or closes search), go back to folder they were in before search
|
||||
if (elfinder_object && elfinder_object.length) {
|
||||
var fm = elfinder_object.elfinder('instance');
|
||||
if (fm) {
|
||||
var cwdBeforeSearch = null;
|
||||
fm.bind('searchstart', function() {
|
||||
var cwd = fm.cwd();
|
||||
if (cwd && cwd.hash) {
|
||||
cwdBeforeSearch = cwd.hash;
|
||||
}
|
||||
});
|
||||
fm.bind('searchend', function() {
|
||||
if (cwdBeforeSearch && fm.file(cwdBeforeSearch)) {
|
||||
fm.exec('open', cwdBeforeSearch);
|
||||
}
|
||||
cwdBeforeSearch = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add Content search radio button after elFinder is initialized
|
||||
if (elfinder_object && elfinder_object.length) {
|
||||
var fm = elfinder_object.elfinder('instance');
|
||||
if (fm) {
|
||||
var addContentRadioButton = function() {
|
||||
var searchMenu = jQuery('.elfinder-button-search-menu');
|
||||
if (searchMenu.length) {
|
||||
var namespace = fm.namespace || 'elfinder-';
|
||||
var id = function(name) {
|
||||
return namespace + (fm.escape ? fm.escape(name) : name);
|
||||
};
|
||||
|
||||
var searchTypeSet = searchMenu.find('.elfinder-search-type');
|
||||
if (searchTypeSet.length && !searchTypeSet.find('#' + id('SearchTag')).length) {
|
||||
var tagRadio = jQuery('<input id="' + id('SearchTag') + '" name="serchcol" type="radio" value="SearchTag"/>');
|
||||
var tagLabel = jQuery('<label for="' + id('SearchTag') + '">Content</label>');
|
||||
|
||||
searchTypeSet.append(tagRadio).append(tagLabel);
|
||||
searchTypeSet.buttonset('refresh');
|
||||
|
||||
// Remember search type when target is "Here", so we can restore only when user had chosen Content then switched to "All"
|
||||
var lastSearchTypeWhenHere = null;
|
||||
|
||||
var updateContentState = function() {
|
||||
var isHere = jQuery('#' + id('SearchFromCwd')).prop('checked');
|
||||
var tagRadio = jQuery('#' + id('SearchTag'));
|
||||
var tagLabel = tagRadio.next('label');
|
||||
|
||||
if (tagRadio.length) {
|
||||
if (isHere) {
|
||||
tagRadio.prop('disabled', false);
|
||||
tagLabel.css({'opacity': '1', 'cursor': 'pointer'});
|
||||
// Restore Content when switching back to "Here" if it was selected before
|
||||
if (lastSearchTypeWhenHere === 'SearchTag') {
|
||||
tagRadio.prop('checked', true);
|
||||
searchTypeSet.buttonset('refresh');
|
||||
}
|
||||
} else {
|
||||
tagRadio.prop('disabled', true);
|
||||
tagLabel.css({'opacity': '0.5', 'cursor': 'not-allowed'});
|
||||
if (tagRadio.prop('checked')) {
|
||||
lastSearchTypeWhenHere = 'SearchTag'; // was Content before switching to All
|
||||
jQuery('#' + id('SearchName')).prop('checked', true).trigger('change');
|
||||
searchTypeSet.buttonset('refresh');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// When user changes search type while target is "Here", remember it
|
||||
searchMenu.off('change.contentsearch', 'input[name="serchcol"]').on('change.contentsearch', 'input[name="serchcol"]', function() {
|
||||
if (jQuery('#' + id('SearchFromCwd')).prop('checked')) {
|
||||
var val = jQuery(this).val();
|
||||
if (val) lastSearchTypeWhenHere = val;
|
||||
}
|
||||
});
|
||||
|
||||
searchMenu.off('change.contentsearch', 'input[name="serchfrom"]').on('change.contentsearch', 'input[name="serchfrom"]', updateContentState);
|
||||
updateContentState();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jQuery(document).on('click focus', '.elfinder-button-search input[type="text"]', function() {
|
||||
setTimeout(addContentRadioButton, 200);
|
||||
});
|
||||
|
||||
fm.bind('open', function() {
|
||||
setTimeout(addContentRadioButton, 500);
|
||||
});
|
||||
|
||||
setTimeout(addContentRadioButton, 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
jQuery(document).ready(function() {
|
||||
var fmakey = jQuery('#fmakey').val();
|
||||
jQuery('#file_manager_advanced').elfinder(
|
||||
// 1st Arg - options
|
||||
{
|
||||
cssAutoLoad : false, // Disable CSS auto loading
|
||||
url : ajaxurl, // connector URL (REQUIRED)
|
||||
customData : {action: 'fma_load_fma_ui',_fmakey: fmakey}, // language (OPTIONAL)
|
||||
},
|
||||
// 2nd Arg - before boot up function
|
||||
function(fm, extraObj) {
|
||||
// `init` event callback function
|
||||
fm.bind('init', function() {
|
||||
// Optional for Japanese decoder "extras/encoding-japanese.min"
|
||||
delete fm.options.rawStringDecoder;
|
||||
if (fm.lang === 'jp') {
|
||||
fm.loadScript(
|
||||
[ fm.baseUrl + '/lib/js/extras/encoding-japanese.min.js' ],
|
||||
function() {
|
||||
if (window.Encoding && Encoding.convert) {
|
||||
fm.options.rawStringDecoder = function(s) {
|
||||
return Encoding.convert(s,{to:'UNICODE',type:'string'});
|
||||
};
|
||||
}
|
||||
},
|
||||
{ loadType: 'tag' }
|
||||
);
|
||||
}
|
||||
});
|
||||
// Optional for set document.title dynamically.
|
||||
var title = document.title;
|
||||
fm.bind('open', function() {
|
||||
var path = '',
|
||||
cwd = fm.cwd();
|
||||
if (cwd) {
|
||||
path = fm.path(cwd.hash) || null;
|
||||
}
|
||||
document.title = path? path + ':' + title : title;
|
||||
}).bind('destroy', function() {
|
||||
document.title = title;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1,319 @@
|
||||
/**
|
||||
* FMA Enhanced Debug JavaScript
|
||||
*
|
||||
* Enhanced debugging capabilities for code editor
|
||||
*
|
||||
* @package Advanced File Manager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
// Debug panel object
|
||||
var FMA_Debug = {
|
||||
init: function() {
|
||||
this.bindEvents();
|
||||
this.createDebugPanel();
|
||||
},
|
||||
|
||||
bindEvents: function() {
|
||||
// Add debug button to code editor
|
||||
$(document).on('click', '.fma-debug-toggle', this.toggleDebugPanel);
|
||||
$(document).on('click', '.fma-debug-close', this.closeDebugPanel);
|
||||
$(document).on('click', '.fma-debug-tab', this.switchTab);
|
||||
$(document).on('click', '#validate-php-btn', this.validatePHP);
|
||||
$(document).on('click', '#test-functions-btn', this.testExecFunctions);
|
||||
},
|
||||
|
||||
createDebugPanel: function() {
|
||||
var debugPanel = `
|
||||
<div id="fma-debug-panel" class="fma-debug-panel" style="display: none;">
|
||||
<div class="fma-debug-header">
|
||||
<h3>Enhanced Debug Panel</h3>
|
||||
<button type="button" class="fma-debug-close">×</button>
|
||||
</div>
|
||||
|
||||
<div class="fma-debug-content">
|
||||
<div class="fma-debug-tabs">
|
||||
<button class="fma-debug-tab active" data-tab="validation">PHP Validation</button>
|
||||
<button class="fma-debug-tab" data-tab="functions">Exec Functions</button>
|
||||
<button class="fma-debug-tab" data-tab="info">System Info</button>
|
||||
</div>
|
||||
|
||||
<div class="fma-debug-tab-content" id="validation-tab">
|
||||
<div class="fma-debug-section">
|
||||
<h4>PHP Syntax Validation</h4>
|
||||
<div class="fma-debug-status">
|
||||
<span class="fma-status-indicator" id="validation-status">
|
||||
<span class="fma-status-icon">⏳</span>
|
||||
</span>
|
||||
<span class="fma-status-text" id="validation-text">
|
||||
Checking validation availability...
|
||||
</span>
|
||||
</div>
|
||||
<button type="button" class="fma-debug-btn" id="validate-php-btn">
|
||||
Validate Current Code
|
||||
</button>
|
||||
<div id="validation-results" class="fma-debug-results"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fma-debug-tab-content" id="functions-tab">
|
||||
<div class="fma-debug-section">
|
||||
<h4>Exec Functions Status</h4>
|
||||
<button type="button" class="fma-debug-btn" id="test-functions-btn">
|
||||
Test All Functions
|
||||
</button>
|
||||
<div id="functions-results" class="fma-debug-results"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fma-debug-tab-content" id="info-tab">
|
||||
<div class="fma-debug-section">
|
||||
<h4>System Information</h4>
|
||||
<div class="fma-debug-info" id="system-info">
|
||||
<p>Loading system information...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$('body').append(debugPanel);
|
||||
this.loadSystemInfo();
|
||||
},
|
||||
|
||||
toggleDebugPanel: function(e) {
|
||||
e.preventDefault();
|
||||
$('#fma-debug-panel').slideToggle();
|
||||
},
|
||||
|
||||
closeDebugPanel: function() {
|
||||
$('#fma-debug-panel').slideUp();
|
||||
},
|
||||
|
||||
switchTab: function(e) {
|
||||
e.preventDefault();
|
||||
var tab = $(this).data('tab');
|
||||
|
||||
// Update tab buttons
|
||||
$('.fma-debug-tab').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
|
||||
// Update tab content
|
||||
$('.fma-debug-tab-content').hide();
|
||||
$('#' + tab + '-tab').show();
|
||||
},
|
||||
|
||||
validatePHP: function() {
|
||||
var $btn = $(this);
|
||||
var $results = $('#validation-results');
|
||||
|
||||
$btn.prop('disabled', true).text('Validating...');
|
||||
$results.html('<div class="fma-loading">Validating PHP syntax...</div>');
|
||||
|
||||
// Get current editor content
|
||||
var phpCode = '';
|
||||
if (typeof editor !== 'undefined' && editor.getValue) {
|
||||
phpCode = editor.getValue();
|
||||
} else {
|
||||
// Fallback to textarea
|
||||
phpCode = $('textarea[name="content"]').val() || '';
|
||||
}
|
||||
|
||||
if (!phpCode.trim()) {
|
||||
$results.html('<div class="fma-error">No PHP code to validate</div>');
|
||||
$btn.prop('disabled', false).text('Validate Current Code');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'fma_validate_php',
|
||||
php_code: phpCode,
|
||||
filename: 'debug.php',
|
||||
nonce: fmaDebug.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
FMA_Debug.displayValidationResults(response);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$results.html('<div class="fma-error">Validation failed: ' + error + '</div>');
|
||||
},
|
||||
complete: function() {
|
||||
$btn.prop('disabled', false).text('Validate Current Code');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
displayValidationResults: function(response) {
|
||||
var $results = $('#validation-results');
|
||||
var html = '';
|
||||
|
||||
if (response.valid) {
|
||||
html = '<div class="fma-success">';
|
||||
html += '<strong>✓ PHP syntax is valid</strong>';
|
||||
if (response.php_version) {
|
||||
html += '<br>PHP Version: ' + response.php_version;
|
||||
}
|
||||
if (response.execution_time) {
|
||||
html += '<br>Validation time: ' + response.execution_time + 'ms';
|
||||
}
|
||||
html += '</div>';
|
||||
} else {
|
||||
html = '<div class="fma-error">';
|
||||
html += '<strong>✗ PHP syntax errors found</strong>';
|
||||
|
||||
if (response.errors && response.errors.length > 0) {
|
||||
html += '<ul class="fma-error-list">';
|
||||
response.errors.forEach(function(error) {
|
||||
html += '<li>';
|
||||
html += '<strong>Line ' + error.line + ':</strong> ';
|
||||
html += error.message;
|
||||
if (error.type) {
|
||||
html += ' <span class="fma-error-type">(' + error.type + ')</span>';
|
||||
}
|
||||
html += '</li>';
|
||||
});
|
||||
html += '</ul>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
$results.html(html);
|
||||
},
|
||||
|
||||
testExecFunctions: function() {
|
||||
var $btn = $(this);
|
||||
var $results = $('#functions-results');
|
||||
|
||||
$btn.prop('disabled', true).text('Testing...');
|
||||
$results.html('<div class="fma-loading">Testing exec functions...</div>');
|
||||
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'fma_test_exec_functions',
|
||||
nonce: fmaDebug.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
FMA_Debug.displayFunctionResults(response.data);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$results.html('<div class="fma-error">Test failed: ' + error + '</div>');
|
||||
},
|
||||
complete: function() {
|
||||
$btn.prop('disabled', false).text('Test All Functions');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
displayFunctionResults: function(results) {
|
||||
var $results = $('#functions-results');
|
||||
var html = '<div class="fma-function-results">';
|
||||
|
||||
Object.keys(results).forEach(function(func) {
|
||||
var result = results[func];
|
||||
var statusClass = result.working ? 'working' : (result.available ? 'available' : 'unavailable');
|
||||
var statusIcon = result.working ? '✓' : (result.available ? '⚠' : '✗');
|
||||
var statusText = result.working ? 'Working' : (result.available ? 'Available' : 'Unavailable');
|
||||
|
||||
html += '<div class="fma-function-item ' + statusClass + '">';
|
||||
html += '<div class="fma-function-name">' + func + '</div>';
|
||||
html += '<div class="fma-function-status">';
|
||||
html += '<span class="fma-status-icon">' + statusIcon + '</span>';
|
||||
html += '<span class="fma-status-text">' + statusText + '</span>';
|
||||
html += '</div>';
|
||||
|
||||
if (result.error) {
|
||||
html += '<div class="fma-function-error">Error: ' + result.error + '</div>';
|
||||
}
|
||||
|
||||
if (result.output) {
|
||||
html += '<div class="fma-function-output">Output: ' + result.output + '</div>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
});
|
||||
|
||||
html += '</div>';
|
||||
$results.html(html);
|
||||
},
|
||||
|
||||
loadSystemInfo: function() {
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'fma_get_debug_info',
|
||||
nonce: fmaDebug.nonce
|
||||
},
|
||||
success: function(response) {
|
||||
FMA_Debug.displaySystemInfo(response.data);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$('#system-info').html('<div class="fma-error">Failed to load system info: ' + error + '</div>');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
displaySystemInfo: function(info) {
|
||||
var html = '';
|
||||
|
||||
html += '<p><strong>PHP Version:</strong> ' + info.php_version + '</p>';
|
||||
html += '<p><strong>PHP Binary:</strong> ' + info.php_binary + '</p>';
|
||||
|
||||
if (info.php_path) {
|
||||
html += '<p><strong>PHP Path:</strong> ' + info.php_path + '</p>';
|
||||
}
|
||||
|
||||
html += '<p><strong>ExecWithFallback:</strong> ';
|
||||
html += info.exec_with_fallback_available ?
|
||||
'<span class="fma-success">✓ Available</span>' :
|
||||
'<span class="fma-error">✗ Not Available</span>';
|
||||
html += '</p>';
|
||||
|
||||
html += '<p><strong>Validation Available:</strong> ';
|
||||
html += info.validation_available ?
|
||||
'<span class="fma-success">✓ Yes</span>' :
|
||||
'<span class="fma-error">✗ No</span>';
|
||||
html += '</p>';
|
||||
|
||||
// Update validation status
|
||||
$('#validation-status').html(
|
||||
info.validation_available ?
|
||||
'<span class="fma-status-icon fma-success">✓</span>' :
|
||||
'<span class="fma-status-icon fma-error">✗</span>'
|
||||
);
|
||||
$('#validation-text').text(
|
||||
info.validation_available ?
|
||||
'PHP validation is available' :
|
||||
'PHP validation is not available'
|
||||
);
|
||||
|
||||
$('#system-info').html(html);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize when document is ready
|
||||
$(document).ready(function() {
|
||||
FMA_Debug.init();
|
||||
});
|
||||
|
||||
// Add debug button to code editor when it loads
|
||||
$(document).on('DOMNodeInserted', function(e) {
|
||||
if ($(e.target).find('.CodeMirror').length > 0) {
|
||||
if (!$('.fma-debug-toggle').length) {
|
||||
var debugButton = '<button type="button" class="fma-debug-toggle button button-secondary" style="margin-left: 10px;">🐛 Debug</button>';
|
||||
$(e.target).find('.CodeMirror').after(debugButton);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* elFinder custom commands for File Manager Advanced
|
||||
*/
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
if (typeof elFinder !== 'undefined' && elFinder.prototype && elFinder.prototype.commands) {
|
||||
|
||||
// Icon CSS
|
||||
var pluginUrl = (typeof afm_object !== 'undefined') ? afm_object.plugin_url : '';
|
||||
if (!pluginUrl) {
|
||||
// Try to find it from script src
|
||||
var script = $('script[src*="fma-elfinder-commands.js"]');
|
||||
if (script.length) {
|
||||
pluginUrl = script.attr('src').split('application/assets/js/')[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginUrl) {
|
||||
var iconStyle = `
|
||||
<style id="fma-replace-icon">
|
||||
.elfinder-button-icon-replace {
|
||||
background-image: url(${pluginUrl}application/assets/images/replace.png) !important;
|
||||
background-size: 16px !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: center !important;
|
||||
}
|
||||
.elfinder-contextmenu-icon-replace {
|
||||
background-image: url(${pluginUrl}application/assets/images/replace.png) !important;
|
||||
background-size: 16px !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: center !important;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
if ($('#fma-replace-icon').length === 0) {
|
||||
$('head').append(iconStyle);
|
||||
}
|
||||
}
|
||||
|
||||
// Translation
|
||||
var i18Obj = elFinder.prototype.i18 || elFinder.prototype.i18n;
|
||||
if (i18Obj) {
|
||||
// Ensure English is initialized if not present
|
||||
if (!i18Obj.en) {
|
||||
i18Obj.en = { messages: {} };
|
||||
}
|
||||
for (var lang in i18Obj) {
|
||||
if (i18Obj.hasOwnProperty(lang)) {
|
||||
var msg = 'Replace';
|
||||
// Add some common translations
|
||||
if (lang === 'es') msg = 'Reemplazar';
|
||||
if (lang === 'fr') msg = 'Remplacer';
|
||||
if (lang === 'de') msg = 'Ersetzen';
|
||||
if (lang === 'it') msg = 'Sostituisci';
|
||||
if (lang === 'pt') msg = 'Substituir';
|
||||
if (lang === 'ru') msg = 'Заменить';
|
||||
if (lang === 'zh_CN') msg = '替换';
|
||||
|
||||
if (!i18Obj[lang].messages) {
|
||||
i18Obj[lang].messages = {};
|
||||
}
|
||||
i18Obj[lang].messages.cmdreplace = msg;
|
||||
i18Obj[lang].messages.replace = msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace command definition
|
||||
elFinder.prototype.commands.replace = function () {
|
||||
this.updateOnSelect = false;
|
||||
this.title = 'Replace';
|
||||
|
||||
this.getstate = function (hashes) {
|
||||
var fm = this.fm;
|
||||
var sel = this.hashes(hashes);
|
||||
var cnt = sel.length;
|
||||
|
||||
if (cnt !== 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var file = fm.file(sel[0]);
|
||||
if (!file || file.mime === 'directory' || file.phash === null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fm.isCommandEnabled('upload', sel[0]) ? 0 : -1;
|
||||
};
|
||||
|
||||
this.exec = function (hashes) {
|
||||
var fm = this.fm;
|
||||
var sel = this.hashes(hashes);
|
||||
var file = fm.file(sel[0]);
|
||||
var self = this;
|
||||
|
||||
if (!file) {
|
||||
return $.Deferred().reject();
|
||||
}
|
||||
|
||||
var input = $('<input type="file" />');
|
||||
|
||||
input.on('change', function () {
|
||||
if (this.files && this.files.length) {
|
||||
var selectedFile = this.files[0];
|
||||
var formData = new FormData();
|
||||
formData.append('cmd', 'upload');
|
||||
formData.append('target', file.phash);
|
||||
formData.append('overwrite', '1');
|
||||
formData.append('upload[]', selectedFile, file.name);
|
||||
|
||||
// Add custom data (nonce, action, etc. required by WordPress and the plugin)
|
||||
var customData = fm.options.customData || {};
|
||||
if (typeof customData === 'function') {
|
||||
customData = customData('upload', fm);
|
||||
}
|
||||
|
||||
|
||||
for (var key in customData) {
|
||||
if (customData.hasOwnProperty(key)) {
|
||||
if (!formData.has(key)) { // Prevent overwriting existing formData keys like 'cmd' or 'target'
|
||||
formData.append(key, customData[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use jQuery.ajax directly for upload to avoid elFinder request stripping FormData issues
|
||||
$.ajax({
|
||||
url: fm.options.url,
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
beforeSend: function () {
|
||||
fm.notify({ type: 'upload', cnt: 1, hide: false });
|
||||
},
|
||||
success: function (data) {
|
||||
// Always decrement the counter
|
||||
fm.notify({ type: 'upload', cnt: -1, hide: true });
|
||||
|
||||
// Try to parse if it's a string
|
||||
if (typeof data === 'string') {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
if (data && data.error) {
|
||||
fm.error(data.error);
|
||||
} else {
|
||||
fm.notify({
|
||||
type: 'info',
|
||||
msg: 'File replaced successfully!',
|
||||
hide: 3000
|
||||
});
|
||||
// Refresh the UI to show the new file immediately
|
||||
if (typeof fm.exec === 'function') {
|
||||
fm.exec('reload');
|
||||
}
|
||||
if (typeof fm.sync === 'function') {
|
||||
fm.sync();
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
fm.notify({ type: 'upload', cnt: -1, hide: true });
|
||||
console.error('FMA Replace Error:', error, xhr.responseText);
|
||||
fm.notify({
|
||||
type: 'error',
|
||||
msg: 'Failed to replace file. Error: ' + error,
|
||||
hide: 3000
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
input.click();
|
||||
return $.Deferred().resolve();
|
||||
};
|
||||
};
|
||||
|
||||
// Function to add replace to context menu
|
||||
var addReplaceToContextMenu = function (opts) {
|
||||
if (opts && opts.contextmenu && opts.contextmenu.files) {
|
||||
var filesMenu = opts.contextmenu.files;
|
||||
if (filesMenu.indexOf('replace') === -1) {
|
||||
var renameIdx = filesMenu.indexOf('rename');
|
||||
if (renameIdx !== -1) {
|
||||
filesMenu.splice(renameIdx + 1, 0, 'replace');
|
||||
} else {
|
||||
filesMenu.push('replace');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add to context menu for ALL future instances (by modifying the prototype _options)
|
||||
if (elFinder && elFinder.prototype && elFinder.prototype._options) {
|
||||
addReplaceToContextMenu(elFinder.prototype._options);
|
||||
}
|
||||
|
||||
// Also handle existing and new instances
|
||||
var setupInstance = function (fm) {
|
||||
if (fm && fm.options) {
|
||||
addReplaceToContextMenu(fm.options);
|
||||
}
|
||||
|
||||
// Get the translation based on current language
|
||||
var msg = 'Replace';
|
||||
var lang = fm.lang || (fm.options && fm.options.lang) || 'en';
|
||||
if (lang === 'es') msg = 'Reemplazar';
|
||||
if (lang === 'fr') msg = 'Remplacer';
|
||||
if (lang === 'de') msg = 'Ersetzen';
|
||||
if (lang === 'it') msg = 'Sostituisci';
|
||||
if (lang === 'pt') msg = 'Substituir';
|
||||
if (lang === 'ru') msg = 'Заменить';
|
||||
if (lang === 'zh_CN') msg = '替换';
|
||||
|
||||
// Ensure instance has the translation (FORCE IT)
|
||||
if (fm && fm.messages) {
|
||||
fm.messages.cmdreplace = msg;
|
||||
fm.messages.replace = msg;
|
||||
}
|
||||
// Ensure the command title is capitalized
|
||||
if (fm && fm.commands && fm.commands.replace) {
|
||||
fm.commands.replace.title = msg;
|
||||
}
|
||||
};
|
||||
|
||||
// Apply to any elFinder instances that might already exist
|
||||
if (typeof elFinder !== 'undefined' && typeof elFinder.instances !== 'undefined') {
|
||||
$.each(elFinder.instances, function (id, fm) {
|
||||
setupInstance(fm);
|
||||
});
|
||||
}
|
||||
|
||||
// Hook into elFinder creation event to apply to new instances as they are created
|
||||
$(document).on('elfindercreate', function (event, fm) {
|
||||
setupInstance(fm);
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,672 @@
|
||||
<?php
|
||||
/*
|
||||
@package: File Manager Advanced
|
||||
@Class: class_fma_blocks
|
||||
*/
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (class_exists('class_fma_blocks')) {
|
||||
return;
|
||||
}
|
||||
|
||||
class class_fma_blocks
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Register block post type
|
||||
add_action('init', array($this, 'register_blocks_post_type'));
|
||||
|
||||
// Add meta boxes
|
||||
add_action('add_meta_boxes', array($this, 'add_blocks_meta_boxes'));
|
||||
|
||||
// Save meta boxes
|
||||
add_action('save_post', array($this, 'save_blocks_meta_boxes'));
|
||||
|
||||
// Change submenu to point to blocks post type
|
||||
// Use priority 100 to run after admin_menus class (which runs at default priority 10)
|
||||
add_action('admin_menu', array($this, 'change_blocks_submenu'), 100);
|
||||
|
||||
// Enqueue admin scripts for popup
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 999);
|
||||
|
||||
// Add blur overlay to blocks list page
|
||||
// Use admin_footer to ensure scripts are loaded
|
||||
add_action('admin_footer', array($this, 'add_blocks_list_blur_overlay'));
|
||||
add_filter('manage_fma_blocks_posts_columns', array($this, 'set_custom_columns'));
|
||||
add_action('manage_fma_blocks_posts_custom_column', array($this, 'custom_column_content'), 10, 2);
|
||||
}
|
||||
|
||||
public function set_custom_columns($columns)
|
||||
{
|
||||
// Remove and re-add columns in desired order
|
||||
$new_columns = [];
|
||||
|
||||
// Keep the checkbox column first
|
||||
if (isset($columns['cb'])) {
|
||||
$new_columns['cb'] = $columns['cb'];
|
||||
}
|
||||
|
||||
// 1️⃣ Title column
|
||||
$new_columns['title'] = __('Title');
|
||||
|
||||
// 2️⃣ Custom columns (Shortcode, Status, Block Type)
|
||||
$new_columns['shortcode'] = __('Shortcode');
|
||||
$new_columns['status_col'] = __('Status');
|
||||
$new_columns['block_type'] = __('Block Type');
|
||||
$new_columns['updated'] = __('Updated');
|
||||
|
||||
// 3️⃣ Bring back updated and date columns at the end if exist
|
||||
if (isset($columns['date'])) {
|
||||
$new_columns['date'] = $columns['date'];
|
||||
}
|
||||
|
||||
return $new_columns;
|
||||
}
|
||||
|
||||
public function custom_column_content($column, $post_id)
|
||||
{
|
||||
if ($column === 'shortcode') {
|
||||
$shortcode_id = get_post_meta($post_id, 'shortcode_id', true);
|
||||
$title = get_the_title($post_id);
|
||||
$shortcode = '[advanced_file_manager_front id="' . esc_attr($shortcode_id) . '" title="' . esc_attr($title) . '"]';
|
||||
|
||||
echo '
|
||||
<div style="display:flex; align-items:center; gap:5px;"> <!-- smaller gap -->
|
||||
<input
|
||||
type="text"
|
||||
readonly
|
||||
value="' . esc_attr($shortcode) . '"
|
||||
style="
|
||||
width: 460px; /* ⬅️ wider input field */
|
||||
background: #f9f9f9;
|
||||
border: 1px solid #ddd;
|
||||
padding: 5px 8px;
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
border-radius: 4px;
|
||||
line-height: 1.4;
|
||||
"
|
||||
/>
|
||||
<button
|
||||
class="copy-shortcode button button-small"
|
||||
data-shortcode="' . esc_attr($shortcode) . '"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 28px;
|
||||
cursor: pointer;
|
||||
padding: 0 8px;
|
||||
"
|
||||
title="Copy Shortcode"
|
||||
>
|
||||
📋
|
||||
</button>
|
||||
</div>';
|
||||
}
|
||||
|
||||
if ($column === 'status_col') {
|
||||
$status = get_post_meta($post_id, 'status_label', true);
|
||||
if ($status === 'Active') {
|
||||
echo '<span style="color:green;font-weight:600;">● Active</span>';
|
||||
} else {
|
||||
echo '<span style="color:red;font-weight:600;">● Inactive</span>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($column === 'block_type') {
|
||||
$block_type = get_post_meta($post_id, 'block_type', true);
|
||||
if ($block_type === 'Logged In') {
|
||||
echo '<span style="color:green;font-weight:600;">Logged In</span>';
|
||||
} else {
|
||||
echo '<span style="font-weight:600;">Non Logged In</span>';
|
||||
}
|
||||
}
|
||||
if ($column === 'updated') {
|
||||
$modified = get_post_modified_time('M j, Y g:i A', false, $post_id);
|
||||
echo esc_html($modified);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue admin scripts
|
||||
*/
|
||||
public function enqueue_admin_scripts($hook)
|
||||
{
|
||||
// Only load on blocks post type pages
|
||||
$screen = get_current_screen();
|
||||
if ($screen && $screen->post_type === 'fma_blocks') {
|
||||
// Enqueue jQuery if not already loaded
|
||||
wp_enqueue_script('jquery');
|
||||
|
||||
// Use the same select2 handle that's registered in class_fma_main
|
||||
// This ensures select2 is available before afm-scripts.js loads
|
||||
wp_enqueue_style('afm-jquery.select2', FMA_PLUGIN_URL . 'application/assets/css/select2/jquery.select2.min.css', array(), FMA_VERSION, 'all');
|
||||
wp_enqueue_script('afm-jquery.select2', FMA_PLUGIN_URL . 'application/assets/js/select2/jquery.select2.min.js', array('jquery'), FMA_VERSION, false);
|
||||
|
||||
// Enqueue admin scripts that contain popup function
|
||||
// Use same handle as class_fma_main for consistency
|
||||
wp_enqueue_style('afm-admin', FMA_PLUGIN_URL . 'application/assets/css/afm-styles.css', array('afm-jquery.select2'), FMA_VERSION, 'all');
|
||||
wp_enqueue_script('afm-admin', FMA_PLUGIN_URL . 'application/assets/js/afm-scripts.js', array('afm-jquery.select2'), FMA_VERSION, false);
|
||||
|
||||
// Localize script with admin URL (same as class_fma_main)
|
||||
wp_localize_script('afm-admin', 'afmAdmin', array(
|
||||
'assetsURL' => FMA_PLUGIN_URL . 'application/assets/',
|
||||
'jsonURL' => rest_url(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Blocks Post Type
|
||||
*/
|
||||
public function register_blocks_post_type()
|
||||
{
|
||||
// Only register if pro plugin is not active
|
||||
if (class_exists('file_manager_advanced_shortcode')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$labels = array(
|
||||
'name' => _x('Blocks', 'Post type general name', 'file-manager-advanced'),
|
||||
'singular_name' => _x('Block', 'Post type singular name', 'file-manager-advanced'),
|
||||
'menu_name' => _x('File Managers', 'Admin Menu text', 'file-manager-advanced'),
|
||||
'add_new' => __('Add New', 'file-manager-advanced'),
|
||||
'add_new_item' => __('Add New Block', 'file-manager-advanced'),
|
||||
'new_item' => __('New Block', 'file-manager-advanced'),
|
||||
'edit_item' => __('Edit Block', 'file-manager-advanced'),
|
||||
'view_item' => __('View Block', 'file-manager-advanced'),
|
||||
'all_items' => __('All Blocks', 'file-manager-advanced'),
|
||||
'search_items' => __('Search Blocks', 'file-manager-advanced'),
|
||||
'not_found' => __('No blocks found.', 'file-manager-advanced'),
|
||||
'not_found_in_trash' => __('No blocks found in Trash.', 'file-manager-advanced'),
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'labels' => $labels,
|
||||
'public' => false,
|
||||
'publicly_queryable' => false,
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false, // We'll add it manually via submenu
|
||||
'query_var' => true,
|
||||
'rewrite' => false,
|
||||
'capability_type' => 'post',
|
||||
'has_archive' => false,
|
||||
'hierarchical' => false,
|
||||
'menu_position' => null,
|
||||
'menu_icon' => 'dashicons-media-archive',
|
||||
'supports' => array('title'),
|
||||
'show_in_rest' => false, // Disable Gutenberg
|
||||
);
|
||||
|
||||
register_post_type('fma_blocks', $args);
|
||||
$this->register_blocks_dummy_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register dummy data for blocks post type
|
||||
*/
|
||||
private function register_blocks_dummy_data()
|
||||
{
|
||||
// Run only once to prevent duplicates
|
||||
if (get_option('fma_blocks_dummy_data_created'))
|
||||
return;
|
||||
|
||||
$dummy_blocks = [
|
||||
[
|
||||
'title' => 'Test Block 1',
|
||||
'block_type' => 'Logged In',
|
||||
'shortcode_id' => 'abc123xyz',
|
||||
'status' => 'Active',
|
||||
],
|
||||
[
|
||||
'title' => 'Test Block 2',
|
||||
'block_type' => 'Non Logged In',
|
||||
'shortcode_id' => 'xyz456abc',
|
||||
'status' => 'Inactive',
|
||||
],
|
||||
[
|
||||
'title' => 'Sample Block 3',
|
||||
'block_type' => 'Logged In',
|
||||
'shortcode_id' => 'pqr789lmn',
|
||||
'status' => 'Active',
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($dummy_blocks as $block) {
|
||||
$post_id = wp_insert_post([
|
||||
'post_type' => 'fma_blocks',
|
||||
'post_title' => $block['title'],
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
|
||||
if (!is_wp_error($post_id)) {
|
||||
update_post_meta($post_id, 'block_type', $block['block_type']);
|
||||
update_post_meta($post_id, 'shortcode_id', $block['shortcode_id']);
|
||||
update_post_meta($post_id, 'status_label', $block['status']);
|
||||
}
|
||||
}
|
||||
|
||||
update_option('fma_blocks_dummy_data_created', true);
|
||||
}
|
||||
/**
|
||||
* Add meta boxes for blocks post type
|
||||
*/
|
||||
public function add_blocks_meta_boxes()
|
||||
{
|
||||
// Only add if pro plugin is not active
|
||||
if (class_exists('file_manager_advanced_shortcode')) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_meta_box(
|
||||
'fma_blocks_pro_overlay',
|
||||
__('Block Configuration', 'file-manager-advanced'),
|
||||
array($this, 'blocks_pro_overlay_meta_box_callback'),
|
||||
'fma_blocks',
|
||||
'normal',
|
||||
'high'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks Pro Overlay Meta Box Callback
|
||||
*/
|
||||
public function blocks_pro_overlay_meta_box_callback($post)
|
||||
{
|
||||
?>
|
||||
<div class="fma__blocks-wrapper" style="position: relative;">
|
||||
<!-- Blur Overlay -->
|
||||
<div class="fma__blocks-blur-overlay" style="
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
backdrop-filter: blur(5px);
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
">
|
||||
<div style="text-align: center; padding: 20px;">
|
||||
<img src="<?php echo esc_url(FMA_PLUGIN_URL . 'application/assets/images/crown.svg'); ?>" alt="Pro Feature"
|
||||
style="width: 60px; margin-bottom: 15px;">
|
||||
<h3 style="margin: 10px 0; color: #333;"><?php _e('This is a Pro Feature', 'file-manager-advanced'); ?>
|
||||
</h3>
|
||||
<p style="color: #666; margin: 10px 0;">
|
||||
<?php _e('Upgrade to Advanced File Manager Pro to unlock this feature.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
<a href="https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=blocks_feature&utm_campaign=plugin"
|
||||
target="_blank" class="button button-primary" style="margin-top: 10px;">
|
||||
<?php _e('Get Pro Now', 'file-manager-advanced'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actual Content (Blurred) -->
|
||||
<div style="filter: blur(3px); pointer-events: none; opacity: 0.5; min-height: 400px;">
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th><label><?php _e('Block Type', 'file-manager-advanced'); ?></label></th>
|
||||
<td>
|
||||
<select disabled>
|
||||
<option><?php _e('Logged In Users', 'file-manager-advanced'); ?></option>
|
||||
<option><?php _e('Non Logged In Users', 'file-manager-advanced'); ?></option>
|
||||
</select>
|
||||
<p class="description">
|
||||
<?php _e('Select to generate block for logged in or non logged in users.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label><?php _e('Select User Roles', 'file-manager-advanced'); ?></label></th>
|
||||
<td>
|
||||
<div
|
||||
style="border: 1px solid #ddd; padding: 10px; border-radius: 4px; max-height: 200px; overflow-y: auto;">
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Administrator', 'file-manager-advanced'); ?></label>
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Editor', 'file-manager-advanced'); ?></label>
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Author', 'file-manager-advanced'); ?></label>
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Contributor', 'file-manager-advanced'); ?></label>
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Subscriber', 'file-manager-advanced'); ?></label>
|
||||
</div>
|
||||
<p class="description">
|
||||
<?php _e('Select user roles that can access this block.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label><?php _e('Path', 'file-manager-advanced'); ?></label></th>
|
||||
<td>
|
||||
<input type="text" disabled class="regular-text"
|
||||
placeholder="<?php _e('File manager root path', 'file-manager-advanced'); ?>" />
|
||||
<p class="description">
|
||||
<?php _e('File manager root path. Use "/" for root directory.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label><?php _e('Path Type', 'file-manager-advanced'); ?></label></th>
|
||||
<td>
|
||||
<select disabled>
|
||||
<option><?php _e('Inside WordPress', 'file-manager-advanced'); ?></option>
|
||||
<option><?php _e('Outside WordPress', 'file-manager-advanced'); ?></option>
|
||||
</select>
|
||||
<p class="description">
|
||||
<?php _e('Whether the path is inside or outside WordPress directory.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label><?php _e('Operations', 'file-manager-advanced'); ?></label></th>
|
||||
<td>
|
||||
<div
|
||||
style="border: 1px solid #ddd; padding: 10px; border-radius: 4px; max-height: 200px; overflow-y: auto;">
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Upload', 'file-manager-advanced'); ?></label>
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Download', 'file-manager-advanced'); ?></label>
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Delete', 'file-manager-advanced'); ?></label>
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Create Folder', 'file-manager-advanced'); ?></label>
|
||||
<label style="display: block; margin: 5px 0;"><input type="checkbox" disabled />
|
||||
<?php _e('Rename', 'file-manager-advanced'); ?></label>
|
||||
</div>
|
||||
<p class="description">
|
||||
<?php _e('Select allowed operations for this block.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label><?php _e('View Type', 'file-manager-advanced'); ?></label></th>
|
||||
<td>
|
||||
<select disabled>
|
||||
<option><?php _e('Grid', 'file-manager-advanced'); ?></option>
|
||||
<option><?php _e('List', 'file-manager-advanced'); ?></option>
|
||||
</select>
|
||||
<p class="description">
|
||||
<?php _e('Default view type for the file manager.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label><?php _e('Theme', 'file-manager-advanced'); ?></label></th>
|
||||
<td>
|
||||
<select disabled>
|
||||
<option><?php _e('Light', 'file-manager-advanced'); ?></option>
|
||||
<option><?php _e('Dark', 'file-manager-advanced'); ?></option>
|
||||
<option><?php _e('Grey', 'file-manager-advanced'); ?></option>
|
||||
</select>
|
||||
<p class="description">
|
||||
<?php _e('Choose your preferred theme for the file manager interface.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label><?php _e('Language', 'file-manager-advanced'); ?></label></th>
|
||||
<td>
|
||||
<select disabled>
|
||||
<option><?php _e('English', 'file-manager-advanced'); ?></option>
|
||||
</select>
|
||||
<p class="description">
|
||||
<?php _e('Select the language for the file manager interface.', 'file-manager-advanced'); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
jQuery(document).ready(function ($) {
|
||||
$('.fma__blocks-blur-overlay').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
if (typeof file_manager_advanced_popup === 'function') {
|
||||
file_manager_advanced_popup(
|
||||
'https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=blocks_feature&utm_campaign=plugin',
|
||||
'Get advanced features with Advanced File Manager Pro!',
|
||||
'Get Pro Now'
|
||||
);
|
||||
} else {
|
||||
// Fallback if popup function not available
|
||||
window.open('https://advancedfilemanager.com/pricing/?utm_source=plugin&utm_medium=blocks_feature&utm_campaign=plugin', '_blank');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta boxes
|
||||
*/
|
||||
public function save_blocks_meta_boxes($post_id)
|
||||
{
|
||||
// Only save if pro plugin is not active
|
||||
if (class_exists('file_manager_advanced_shortcode')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's a blocks post type
|
||||
if (get_post_type($post_id) !== 'fma_blocks') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't save anything - this is just a placeholder
|
||||
}
|
||||
|
||||
/**
|
||||
* Change blocks submenu to point to post type
|
||||
*/
|
||||
public function change_blocks_submenu()
|
||||
{
|
||||
// Only change if pro plugin is not active
|
||||
if (class_exists('file_manager_advanced_shortcode')) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $submenu;
|
||||
|
||||
// Remove old submenu if it exists
|
||||
if (isset($submenu['file_manager_advanced_ui'])) {
|
||||
foreach ($submenu['file_manager_advanced_ui'] as $key => $item) {
|
||||
if (isset($item[2]) && $item[2] === 'file_manager_advanced_shortcodes') {
|
||||
unset($submenu['file_manager_advanced_ui'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add new submenu pointing to blocks post type
|
||||
// This will add it at the end, we'll reorder it below
|
||||
add_submenu_page(
|
||||
'file_manager_advanced_ui',
|
||||
__('Blocks', 'file-manager-advanced'),
|
||||
__('Blocks', 'file-manager-advanced'),
|
||||
'manage_options',
|
||||
'edit.php?post_type=fma_blocks'
|
||||
);
|
||||
|
||||
// Reorder submenu to put Blocks at the original position (after AI Code Pilot, before DB Access)
|
||||
if (isset($submenu['file_manager_advanced_ui']) && is_array($submenu['file_manager_advanced_ui'])) {
|
||||
$blocks_item = null;
|
||||
$menu_items = array();
|
||||
|
||||
// Find and extract blocks item
|
||||
foreach ($submenu['file_manager_advanced_ui'] as $key => $item) {
|
||||
if (isset($item[2]) && $item[2] === 'edit.php?post_type=fma_blocks') {
|
||||
$blocks_item = $item;
|
||||
} else {
|
||||
$menu_items[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert blocks at the correct position
|
||||
if ($blocks_item) {
|
||||
$insert_position = 2; // Default: after Settings (0) and AI Code Pilot (1), so position 2
|
||||
$ai_code_pilot_found = false;
|
||||
|
||||
// Find AI Code Pilot position
|
||||
foreach ($menu_items as $index => $item) {
|
||||
if (isset($item[2]) && $item[2] === 'ai-code-pilot') {
|
||||
$insert_position = $index + 1; // Insert after AI Code Pilot
|
||||
$ai_code_pilot_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If AI Code Pilot not found, insert after Settings (position 1)
|
||||
if (!$ai_code_pilot_found) {
|
||||
$insert_position = 1;
|
||||
}
|
||||
|
||||
// Insert blocks at the calculated position
|
||||
array_splice($menu_items, $insert_position, 0, array($blocks_item));
|
||||
|
||||
// Update submenu
|
||||
$submenu['file_manager_advanced_ui'] = $menu_items;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add blur overlay to blocks list page (same style as OneDrive/Dropbox)
|
||||
*/
|
||||
public function add_blocks_list_blur_overlay()
|
||||
{
|
||||
// Only add if pro plugin is not active
|
||||
if (class_exists('file_manager_advanced_shortcode')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only on blocks post type pages
|
||||
$screen = get_current_screen();
|
||||
if (!$screen || $screen->post_type !== 'fma_blocks') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only on list page (edit.php), not on edit page
|
||||
if ($screen->base === 'edit' && $screen->post_type === 'fma_blocks') {
|
||||
?>
|
||||
<style>
|
||||
/* Blocks heading - same style as OneDrive/Dropbox */
|
||||
.fma__blocks__heading {
|
||||
color: #000;
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.fma__blocks__heading-pro-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
background: linear-gradient(270deg, #011D33 0%, #3F6972 100%);
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
margin-left: 15px;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Blocks wrap - same style as OneDrive/Dropbox */
|
||||
.fma__blocks__wrap {
|
||||
opacity: 0.5;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fma__blocks__wrap::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
background: transparent;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
jQuery(document).ready(function ($) {
|
||||
// Add PRO tag heading (same as OneDrive/Dropbox)
|
||||
if ($('.wp-heading-inline').length && !$('.wp-heading-inline').hasClass('fma__blocks__heading-added')) {
|
||||
$('.wp-heading-inline').addClass('fma__blocks__heading-added');
|
||||
$('.wp-heading-inline').addClass('fma__blocks__heading');
|
||||
if ($('.wp-heading-inline').find('.fma__blocks__heading-pro-tag').length === 0) {
|
||||
$('.wp-heading-inline').append('<span class="fma__blocks__heading-pro-tag">PRO</span>');
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap only the table/content area (same as OneDrive/Dropbox)
|
||||
// WordPress post type list page structure: .wrap > heading + #posts-filter + .wp-list-table
|
||||
// We need to wrap everything after the heading, just like OneDrive/Dropbox
|
||||
var $wrap = $('.wrap');
|
||||
if ($wrap.length && !$wrap.find('.fma__blocks__wrap').length) {
|
||||
// Find the heading element
|
||||
var $heading = $wrap.find('.wp-heading-inline').closest('h1, h2');
|
||||
|
||||
if ($heading.length) {
|
||||
// Get all siblings after heading (everything after heading)
|
||||
var $contentToWrap = $heading.nextAll();
|
||||
|
||||
if ($contentToWrap.length > 0) {
|
||||
// Wrap all content after heading (same as OneDrive/Dropbox)
|
||||
$contentToWrap.wrapAll('<div class="fma__blocks__wrap" afmp-href=""></div>');
|
||||
} else {
|
||||
// Fallback: wrap #posts-filter and .wp-list-table together
|
||||
var $postsFilter = $('#posts-filter');
|
||||
var $listTable = $('.wp-list-table');
|
||||
|
||||
if ($postsFilter.length || $listTable.length) {
|
||||
if ($postsFilter.length && $listTable.length) {
|
||||
$postsFilter.add($listTable).wrapAll('<div class="fma__blocks__wrap" afmp-href=""></div>');
|
||||
} else if ($postsFilter.length) {
|
||||
$postsFilter.wrap('<div class="fma__blocks__wrap" afmp-href=""></div>');
|
||||
} else if ($listTable.length) {
|
||||
$listTable.wrap('<div class="fma__blocks__wrap" afmp-href=""></div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No heading found, wrap #posts-filter and .wp-list-table
|
||||
var $postsFilter = $('#posts-filter');
|
||||
var $listTable = $('.wp-list-table');
|
||||
|
||||
if ($postsFilter.length || $listTable.length) {
|
||||
if ($postsFilter.length && $listTable.length) {
|
||||
$postsFilter.add($listTable).wrapAll('<div class="fma__blocks__wrap" afmp-href=""></div>');
|
||||
} else if ($postsFilter.length) {
|
||||
$postsFilter.wrap('<div class="fma__blocks__wrap" afmp-href=""></div>');
|
||||
} else if ($listTable.length) {
|
||||
$listTable.wrap('<div class="fma__blocks__wrap" afmp-href=""></div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
/**
|
||||
* @package: File Manager Advanced
|
||||
* @Class: fma_connector
|
||||
*/
|
||||
if ( class_exists( 'class_fma_connector' ) ) {
|
||||
return;
|
||||
}
|
||||
class class_fma_connector {
|
||||
// elfinder defaults:
|
||||
//read:https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options
|
||||
public function fma_local_file_system() {
|
||||
$settings = get_option('fmaoptions');
|
||||
$path = ABSPATH;
|
||||
|
||||
if ( isset( $settings['public_path'] ) && ! empty($settings['public_path'] ) ) {
|
||||
$path = $settings['public_path'];
|
||||
}
|
||||
|
||||
$url = site_url();
|
||||
|
||||
if ( isset( $settings['public_url'] ) && ! empty( $settings['public_url'] ) ) {
|
||||
$url = $settings['public_url'];
|
||||
}
|
||||
|
||||
if ( isset( $settings['hide_path'] ) && ($settings['hide_path'] == '1' ) ) {
|
||||
$url = '';
|
||||
}
|
||||
|
||||
if ( !function_exists( 'elFinderAutoloader' ) ) {
|
||||
require 'library/php/autoload.php';
|
||||
}
|
||||
|
||||
// Load custom filesystem driver for content search
|
||||
if (defined('FMAFILEPATH')) {
|
||||
require_once FMAFILEPATH . 'application/class_fma_local_filesystem.php';
|
||||
} else {
|
||||
require_once dirname(__FILE__) . '/class_fma_local_filesystem.php';
|
||||
}
|
||||
|
||||
if ( isset( $settings['enable_trash'] ) && ($settings['enable_trash'] == '1' ) ) {
|
||||
$trash = array(
|
||||
'id' => '1',
|
||||
'driver' => 'Trash',
|
||||
'path' => FMAFILEPATH.'application/library/files/.trash/',
|
||||
'tmbURL' => site_url() . '/application/library/files/.trash/.tmb/',
|
||||
'winHashFix' => DIRECTORY_SEPARATOR !== '/', // to make hash same to Linux one on windows too
|
||||
'uploadDeny' => array(''), // Recomend the same settings as the original volume that uses the trash
|
||||
'uploadAllow' => array('all'),// Same as above
|
||||
'uploadOrder' => array('deny', 'allow'), // Same as above
|
||||
'accessControl' => 'access', // Same as above
|
||||
'attributes' => array(
|
||||
array(
|
||||
'pattern' => '/.tmb/',
|
||||
'read' => false,
|
||||
'write' => false,
|
||||
'hidden' => true,
|
||||
'locked' => false,
|
||||
),
|
||||
array(
|
||||
'pattern' => '/.quarantine/',
|
||||
'read' => false,
|
||||
'write' => false,
|
||||
'hidden' => true,
|
||||
'locked' => false,
|
||||
),
|
||||
array(
|
||||
'pattern' => '/.gitkeep/',
|
||||
'read' => false,
|
||||
'write' => false,
|
||||
'hidden' => true,
|
||||
'locked' => false,
|
||||
)
|
||||
),
|
||||
);
|
||||
$trash_f = 't1_Lw';
|
||||
} else {
|
||||
$trash = array();
|
||||
$trash_f = '';
|
||||
}
|
||||
|
||||
$hide_htaccess = array(
|
||||
'pattern' => '/.htaccess/',
|
||||
'read' => false,
|
||||
'write' => false,
|
||||
'hidden' => true,
|
||||
'locked' => false,
|
||||
);
|
||||
|
||||
if ( isset( $settings['enable_htaccess'] ) && ! empty( $settings['enable_htaccess'] ) && $settings['enable_htaccess'] == '1' ) {
|
||||
$hide_htaccess = array(
|
||||
'pattern' => '/.htaccess/',
|
||||
'read' => true,
|
||||
'write' => false,
|
||||
'hidden' => false,
|
||||
'locked' => false,
|
||||
);
|
||||
}
|
||||
|
||||
// getting allowed upload
|
||||
$allowUpload = array( 'all' );
|
||||
|
||||
if ( isset( $settings['fma_upload_allow'] ) && ! empty( $settings['fma_upload_allow'] ) ) {
|
||||
$allowUpload = explode( ',',$settings['fma_upload_allow'] );
|
||||
}
|
||||
|
||||
// restricting max upload size
|
||||
$max_upload_size = isset( $settings['upload_max_size'] ) ? $settings['upload_max_size'] : '0';
|
||||
|
||||
$opts = array(
|
||||
'roots' => array(
|
||||
// Items volume
|
||||
array(
|
||||
'driver' => 'fma_local_filesystem', // custom driver with content search support
|
||||
'path' => $path, // path to files (REQUIRED)
|
||||
'URL' => $url, // URL to files (REQUIRED)
|
||||
'trashHash' => $trash_f, // elFinder's hash of trash folder
|
||||
'winHashFix' => DIRECTORY_SEPARATOR !== '/', // to make hash same to Linux one on windows too
|
||||
'uploadDeny' => current_user_can('manage_options') ? array('all') : array('text/x-php'), // All Mimetypes not allowed to upload
|
||||
'uploadAllow' => $allowUpload,// Mimetype `image` and `text/plain` allowed to upload
|
||||
'uploadOrder' => current_user_can('manage_options') ? array('deny','allow') :array('allow', 'deny'), // allowed Mimetype `image` and `text/plain` only
|
||||
'disabled' => array('help','preference'),
|
||||
'accessControl' => 'access',
|
||||
'acceptedName' => current_user_can('manage_options') ? '' : 'afm_plugin_file_validName',
|
||||
'uploadMaxSize' => $max_upload_size,
|
||||
'searchTimeout' => 300,
|
||||
'attributes' => array(
|
||||
array(
|
||||
'pattern' => '/.tmb/',
|
||||
'read' => false,
|
||||
'write' => false,
|
||||
'hidden' => true,
|
||||
'locked' => false,
|
||||
),
|
||||
array(
|
||||
'pattern' => '/.quarantine/',
|
||||
'read' => false,
|
||||
'write' => false,
|
||||
'hidden' => true,
|
||||
'locked' => false,
|
||||
),
|
||||
array(
|
||||
'pattern' => '/.gitkeep/',
|
||||
'read' => false,
|
||||
'write' => false,
|
||||
'hidden' => true,
|
||||
'locked' => false,
|
||||
),
|
||||
$hide_htaccess
|
||||
),
|
||||
),
|
||||
// Trash volume
|
||||
$trash,
|
||||
),
|
||||
);
|
||||
$opts['bind']['upload'] = array( $this, 'on_upload_event' );
|
||||
$opts['bind']['search.pre'] = array( $this, 'on_search_command' );
|
||||
$opts = apply_filters( 'fma__opts_override', $opts );
|
||||
|
||||
// run elFinder
|
||||
$fma_connector = fma_create_elfinder_connector(new elFinder($opts));
|
||||
try {
|
||||
$fma_connector->run();
|
||||
die;
|
||||
} catch ( Exception $e ) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function on_upload_event( $cmd, &$args, $files, $elfinder, $volume ) {
|
||||
if ( 'upload' === $cmd ) {
|
||||
if ( isset( $args['added'] ) && is_array( $args['added'] ) ) {
|
||||
foreach ( $args['added'] as $key => $uploaded_file ) {
|
||||
if ( isset( $uploaded_file['mime'] ) && ( 'image/svg' === $uploaded_file['mime'] || strpos( $uploaded_file['mime'], 'svg' ) ) ) {
|
||||
$this->sanitize_svg_file_content( $uploaded_file, $volume );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function sanitize_svg_file_content( $uploaded_file, $volume ) {
|
||||
require_once FMAFILEPATH . 'application/svg-sanitizer/includes/autoload.php';
|
||||
if ( isset( $uploaded_file['hash'] ) ) {
|
||||
$file_path = $volume->getPath( $uploaded_file['hash'] );
|
||||
if ( file_exists( $file_path ) ) {
|
||||
$file_content = file_get_contents( $file_path );
|
||||
$svg_sanitizer = new enshrined\svgSanitize\Sanitizer();
|
||||
$file_content = $svg_sanitizer->sanitize( $file_content );
|
||||
file_put_contents( $file_path, $file_content );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept search command to handle content search tag parameter
|
||||
* This hook is called before the search command executes
|
||||
* We decode the tag from q parameter which contains special marker
|
||||
*/
|
||||
public function on_search_command( $cmd, &$args, $elfinder, $volume ) {
|
||||
if ( $cmd === 'search' ) {
|
||||
$type = !empty( $args['type'] ) ? $args['type'] : '';
|
||||
$q = !empty( $args['q'] ) ? trim( $args['q'] ) : '';
|
||||
|
||||
// Content search: type is SearchTag and/or q contains our marker
|
||||
if ( $type === 'SearchTag' || strpos( $q, '__CONTENT_SEARCH__:' ) === 0 ) {
|
||||
$tag = '';
|
||||
if ( strpos( $q, '__CONTENT_SEARCH__:' ) === 0 ) {
|
||||
$tag = substr( $q, strlen( '__CONTENT_SEARCH__:' ) );
|
||||
} elseif ( $type === 'SearchTag' && $q !== '' ) {
|
||||
$tag = $q; // default elFinder sends type=SearchTag and q=term (no marker)
|
||||
}
|
||||
if ( $tag !== '' ) {
|
||||
elFinderVolumefma_local_filesystem::setContentSearchTag( $tag );
|
||||
$args['q'] = '';
|
||||
} else {
|
||||
elFinderVolumefma_local_filesystem::setContentSearchTag( '' );
|
||||
}
|
||||
} else {
|
||||
elFinderVolumefma_local_filesystem::setContentSearchTag( '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Hook to fix invalid and malicious files
|
||||
*/
|
||||
function afm_plugin_file_validName( $name ) {
|
||||
|
||||
if ( ! empty( $name ) ) {
|
||||
// Check for dangerous characters (but allow spaces)
|
||||
// Block characters that could be used for path traversal or command injection
|
||||
if( preg_match( '/[<>:"|?*\x00-\x1F]/', $name ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Block files starting with dot (except for special cases handled elsewhere)
|
||||
if( strpos($name, '.') === 0 && $name !== '.' && $name !== '..' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lower_name = strtolower( $name );
|
||||
|
||||
// Block dangerous file extensions
|
||||
if(
|
||||
strpos($lower_name, '.php') !== false
|
||||
|| strpos($lower_name, '.phtml') !== false
|
||||
|| strpos($lower_name, '.ini') !== false
|
||||
|| strpos($lower_name, '.htaccess') !== false
|
||||
|| strpos($lower_name, '.config') !== false
|
||||
|| strpos($lower_name, '.css') !== false
|
||||
|| strpos($lower_name, '.js') !== false
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filename is valid (allows spaces)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function access($attr, $path, $data, $volume, $isDir, $relpath) {
|
||||
$basename = basename($path);
|
||||
//skipping htaccess
|
||||
if($basename == '.htaccess') {
|
||||
return null;
|
||||
} else {
|
||||
return $basename[0] === '.' // if file/folder begins with '.' (dot)
|
||||
&& strlen($relpath) !== 1 // but with out volume root
|
||||
? !($attr == 'read' || $attr == 'write') // set read+write to false, other (locked+hidden) set to true
|
||||
: null; // else elFinder decide it itself
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
/**
|
||||
* FMA Debug Validator
|
||||
*
|
||||
* Robust PHP syntax validation using exec-with-fallback library
|
||||
* for better compatibility across different hosting environments
|
||||
*
|
||||
* @package Advanced File Manager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Load Pure PHP validator (no exec functions required)
|
||||
if ( file_exists( plugin_dir_path( __FILE__ ) . 'class_fma_pure_php_validator.php' ) ) {
|
||||
require_once plugin_dir_path( __FILE__ ) . 'class_fma_pure_php_validator.php';
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'FMA_Debug_Validator' ) ) :
|
||||
|
||||
/**
|
||||
* Class FMA_Debug_Validator
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class FMA_Debug_Validator {
|
||||
|
||||
/**
|
||||
* Instance of this class
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var FMA_Debug_Validator
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* PHP executable path
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
private $php_path = 'php';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instance
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return FMA_Debug_Validator
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( null === self::$instance ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate PHP syntax
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param string $php_code PHP code to validate
|
||||
* @return array Validation result with success status and errors
|
||||
*/
|
||||
public function validate_syntax( $php_code ) {
|
||||
// Use Pure PHP Validator (no exec functions required)
|
||||
if ( class_exists( 'FMA_Pure_PHP_Validator' ) ) {
|
||||
$pure_validator = FMA_Pure_PHP_Validator::get_instance();
|
||||
return $pure_validator->validate_syntax( $php_code );
|
||||
}
|
||||
|
||||
// Fallback to original method
|
||||
$result = array(
|
||||
'valid' => false,
|
||||
'errors' => array(),
|
||||
'message' => '',
|
||||
'php_version' => '',
|
||||
'execution_time' => 0
|
||||
);
|
||||
|
||||
$start_time = microtime( true );
|
||||
|
||||
try {
|
||||
// Create temporary file
|
||||
$temp_file = $this->create_temp_file( $php_code );
|
||||
if ( ! $temp_file ) {
|
||||
$result['errors'][] = 'Unable to create temporary file for validation';
|
||||
$result['message'] = 'PHP syntax errors found';
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Run PHP syntax check
|
||||
$output = array();
|
||||
$return_code = 0;
|
||||
$command = $this->php_path . ' -l "' . $temp_file . '" 2>&1';
|
||||
|
||||
// Use exec-with-fallback if available
|
||||
if ( class_exists( 'ExecWithFallback\\ExecWithFallback' ) ) {
|
||||
$exec_result = \ExecWithFallback\ExecWithFallback::exec( $command, $output, $return_code );
|
||||
} else {
|
||||
// Fallback to regular exec
|
||||
$exec_result = exec( $command, $output, $return_code );
|
||||
}
|
||||
|
||||
// Get PHP version
|
||||
$version_output = array();
|
||||
if ( class_exists( 'ExecWithFallback\\ExecWithFallback' ) ) {
|
||||
\ExecWithFallback\ExecWithFallback::exec( $this->php_path . ' -v', $version_output );
|
||||
} else {
|
||||
exec( $this->php_path . ' -v', $version_output );
|
||||
}
|
||||
$result['php_version'] = ! empty( $version_output ) ? $version_output[0] : 'PHP ' . PHP_VERSION;
|
||||
|
||||
// Parse results
|
||||
if ( $return_code === 0 ) {
|
||||
$result['valid'] = true;
|
||||
$result['message'] = 'PHP syntax is valid';
|
||||
$result['errors'] = array();
|
||||
} else {
|
||||
$result['valid'] = false;
|
||||
$result['message'] = 'PHP syntax errors found';
|
||||
$result['errors'] = $this->parse_syntax_errors( $output );
|
||||
}
|
||||
|
||||
// Clean up
|
||||
$this->cleanup_temp_file( $temp_file );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
$result['errors'][] = 'Validation failed: ' . $e->getMessage();
|
||||
$result['message'] = 'PHP syntax errors found';
|
||||
}
|
||||
|
||||
$result['execution_time'] = round( ( microtime( true ) - $start_time ) * 1000, 2 );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create temporary file with PHP code
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param string $php_code PHP code
|
||||
* @return string|false Temporary file path or false on failure
|
||||
*/
|
||||
private function create_temp_file( $php_code ) {
|
||||
// Ensure code has proper PHP tags
|
||||
if ( strpos( $php_code, '<?php' ) === false && strpos( $php_code, '<?=' ) === false ) {
|
||||
$php_code = '<?php' . "\n" . $php_code;
|
||||
}
|
||||
|
||||
$temp_file = tempnam( sys_get_temp_dir(), 'fma_php_validation_' );
|
||||
if ( $temp_file === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = file_put_contents( $temp_file, $php_code );
|
||||
if ( $result === false ) {
|
||||
unlink( $temp_file );
|
||||
return false;
|
||||
}
|
||||
|
||||
return $temp_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up temporary file
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param string $temp_file Temporary file path
|
||||
*/
|
||||
private function cleanup_temp_file( $temp_file ) {
|
||||
if ( file_exists( $temp_file ) ) {
|
||||
unlink( $temp_file );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse syntax errors from PHP output
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param array $output PHP command output
|
||||
* @return array Parsed errors
|
||||
*/
|
||||
private function parse_syntax_errors( $output ) {
|
||||
$errors = array();
|
||||
$output_text = implode( "\n", $output );
|
||||
|
||||
// Parse PHP syntax errors
|
||||
if ( preg_match( '/Parse error:\s*(.+?)\s+in\s+(.+?)\s+on\s+line\s+(\d+)/i', $output_text, $matches ) ) {
|
||||
$errors[] = array(
|
||||
'type' => 'parse_error',
|
||||
'message' => trim( $matches[1] ),
|
||||
'file' => basename( $matches[2] ),
|
||||
'line' => intval( $matches[3] ),
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
// Parse fatal errors
|
||||
if ( preg_match( '/Fatal error:\s*(.+?)\s+in\s+(.+?)\s+on\s+line\s+(\d+)/i', $output_text, $matches ) ) {
|
||||
$errors[] = array(
|
||||
'type' => 'fatal_error',
|
||||
'message' => trim( $matches[1] ),
|
||||
'file' => basename( $matches[2] ),
|
||||
'line' => intval( $matches[3] ),
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
// Parse warnings
|
||||
if ( preg_match( '/Warning:\s*(.+?)\s+in\s+(.+?)\s+on\s+line\s+(\d+)/i', $output_text, $matches ) ) {
|
||||
$errors[] = array(
|
||||
'type' => 'warning',
|
||||
'message' => trim( $matches[1] ),
|
||||
'file' => basename( $matches[2] ),
|
||||
'line' => intval( $matches[3] ),
|
||||
'severity' => 'warning'
|
||||
);
|
||||
}
|
||||
|
||||
// If no specific errors found, add generic error
|
||||
if ( empty( $errors ) && ! empty( $output_text ) ) {
|
||||
$errors[] = array(
|
||||
'type' => 'unknown',
|
||||
'message' => trim( $output_text ),
|
||||
'file' => 'unknown',
|
||||
'line' => 0,
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PHP configuration info
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return array PHP configuration
|
||||
*/
|
||||
public function get_php_info() {
|
||||
$info = array(
|
||||
'php_path' => $this->php_path,
|
||||
'php_version' => PHP_VERSION,
|
||||
'php_binary' => PHP_BINARY,
|
||||
'exec_functions' => array(),
|
||||
'disabled_functions' => array(),
|
||||
'exec_with_fallback_available' => class_exists( 'ExecWithFallback\\ExecWithFallback' )
|
||||
);
|
||||
|
||||
// Check available exec functions
|
||||
$exec_functions = array( 'exec', 'system', 'shell_exec', 'passthru', 'proc_open', 'popen' );
|
||||
foreach ( $exec_functions as $func ) {
|
||||
$info['exec_functions'][ $func ] = function_exists( $func ) && ! in_array( $func, explode( ',', ini_get( 'disable_functions' ) ) );
|
||||
}
|
||||
|
||||
// Get disabled functions
|
||||
$disabled = ini_get( 'disable_functions' );
|
||||
$info['disabled_functions'] = ! empty( $disabled ) ? explode( ',', $disabled ) : array();
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if validation is available
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available() {
|
||||
try {
|
||||
$test_code = '<?php echo "test";';
|
||||
$result = $this->validate_syntax( $test_code );
|
||||
return $result['success'];
|
||||
} catch ( Exception $e ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin-level elFinder connector override for stream-safe downloads.
|
||||
*
|
||||
* Keeps vendor library untouched while providing host-compatible output
|
||||
* fallback when fpassthru is unavailable/blocked.
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (class_exists('class_fma_elfinder_connector')) {
|
||||
return;
|
||||
}
|
||||
|
||||
class class_fma_elfinder_connector extends elFinderConnector
|
||||
{
|
||||
/**
|
||||
* Host-safe passthrough fallback.
|
||||
*
|
||||
* @param resource $fp File pointer.
|
||||
* @return void
|
||||
*/
|
||||
protected function fma_stream_passthru($fp)
|
||||
{
|
||||
if (function_exists('fpassthru')) {
|
||||
fpassthru($fp);
|
||||
return;
|
||||
}
|
||||
|
||||
while (!feof($fp)) {
|
||||
$chunk = fread($fp, 8192);
|
||||
if ($chunk === false) {
|
||||
break;
|
||||
}
|
||||
echo $chunk;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override only to customize stream output fallback.
|
||||
*
|
||||
* @param array $data elFinder response.
|
||||
* @return void
|
||||
* @throws elFinderAbortException
|
||||
*/
|
||||
protected function output(array $data)
|
||||
{
|
||||
$this->elFinder->getSession()->close();
|
||||
ignore_user_abort(false);
|
||||
|
||||
if ($this->header) {
|
||||
self::sendHeader($this->header);
|
||||
}
|
||||
|
||||
if (isset($data['pointer'])) {
|
||||
elFinder::extendTimeLimit(0);
|
||||
|
||||
if (!empty($data['header'])) {
|
||||
self::sendHeader($data['header']);
|
||||
}
|
||||
|
||||
while (ob_get_level() && ob_end_clean()) {
|
||||
}
|
||||
|
||||
$toEnd = true;
|
||||
$fp = $data['pointer'];
|
||||
$sendData = !($this->reqMethod === 'HEAD' || !empty($data['info']['xsendfile']));
|
||||
$psize = null;
|
||||
if (($this->reqMethod === 'GET' || !$sendData)
|
||||
&& (elFinder::isSeekableStream($fp) || elFinder::isSeekableUrl($fp))
|
||||
&& (array_search('Accept-Ranges: none', headers_list()) === false)) {
|
||||
header('Accept-Ranges: bytes');
|
||||
if (!empty($_SERVER['HTTP_RANGE'])) {
|
||||
$size = $data['info']['size'];
|
||||
$end = $size - 1;
|
||||
if (preg_match('/bytes=(\d*)-(\d*)(,?)/i', $_SERVER['HTTP_RANGE'], $matches)) {
|
||||
if (empty($matches[3])) {
|
||||
if (empty($matches[1]) && $matches[1] !== '0') {
|
||||
$start = $size - $matches[2];
|
||||
} else {
|
||||
$start = intval($matches[1]);
|
||||
if (!empty($matches[2])) {
|
||||
$end = intval($matches[2]);
|
||||
if ($end >= $size) {
|
||||
$end = $size - 1;
|
||||
}
|
||||
$toEnd = ($end == ($size - 1));
|
||||
}
|
||||
}
|
||||
$psize = $end - $start + 1;
|
||||
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
header('Content-Length: ' . $psize);
|
||||
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $size);
|
||||
|
||||
if (isset($data['info']['xsendfile']) && strtolower($data['info']['xsendfile']) === 'x-sendfile') {
|
||||
if (function_exists('header_remove')) {
|
||||
header_remove($data['info']['xsendfile']);
|
||||
} else {
|
||||
header($data['info']['xsendfile'] . ':');
|
||||
}
|
||||
unset($data['info']['xsendfile']);
|
||||
if ($this->reqMethod !== 'HEAD') {
|
||||
$sendData = true;
|
||||
}
|
||||
}
|
||||
|
||||
$sendData && !elFinder::isSeekableUrl($fp) && fseek($fp, $start);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($sendData && is_null($psize)) {
|
||||
elFinder::rewind($fp);
|
||||
}
|
||||
} else {
|
||||
header('Accept-Ranges: none');
|
||||
if (isset($data['info']) && !$data['info']['size']) {
|
||||
if (function_exists('header_remove')) {
|
||||
header_remove('Content-Length');
|
||||
} else {
|
||||
header('Content-Length:');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($sendData) {
|
||||
if ($toEnd || elFinder::isSeekableUrl($fp)) {
|
||||
if (version_compare(PHP_VERSION, '5.6', '<')) {
|
||||
file_put_contents('php://output', $fp);
|
||||
} else {
|
||||
$this->fma_stream_passthru($fp);
|
||||
}
|
||||
} else {
|
||||
$out = fopen('php://output', 'wb');
|
||||
stream_copy_to_stream($fp, $out, $psize);
|
||||
fclose($out);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['volume'])) {
|
||||
$data['volume']->close($fp, $data['info']['hash']);
|
||||
} else {
|
||||
fclose($fp);
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
self::outputJson($data);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/*
|
||||
@package: File Manager Advanced
|
||||
@Class: fma_admin_menus
|
||||
*/
|
||||
if(class_exists('class_fma_adv_lang')) {
|
||||
return;
|
||||
}
|
||||
class class_fma_adv_lang {
|
||||
// available in elfinder
|
||||
public function locales() {
|
||||
$locales = array('English'=>'en',
|
||||
'Arabic'=>'ar',
|
||||
'Bulgarian' => 'bg',
|
||||
'Catalan' => 'ca',
|
||||
'Czech' => 'cs',
|
||||
'Danish' => 'da',
|
||||
'German' => 'de',
|
||||
'Greek' => 'el',
|
||||
'Español' => 'es',
|
||||
'Persian-Farsi' => 'fa',
|
||||
'Faroese translation' => 'fo',
|
||||
'French' => 'fr',
|
||||
'Hebrew' => 'he',
|
||||
'hr' => 'hr',
|
||||
'magyar' => 'hu',
|
||||
'Indonesian' => 'id',
|
||||
'Italiano' => 'it',
|
||||
'Japanese' => 'ja',
|
||||
'Korean' => 'ko',
|
||||
'Dutch' => 'nl',
|
||||
'Norwegian' => 'no',
|
||||
'Polski' => 'pl',
|
||||
'Português' => 'pt_BR',
|
||||
'Română' => 'ro',
|
||||
'Russian' => 'ru',
|
||||
'Slovak' => 'sk',
|
||||
'Slovenian' => 'sl',
|
||||
'Serbian' => 'sr',
|
||||
'Swedish' => 'sv',
|
||||
'Türkçe' => 'tr',
|
||||
'Uyghur' => 'ug_CN',
|
||||
'Ukrainian' => 'uk',
|
||||
'Vietnamese' => 'vi',
|
||||
'Simplified Chinese' => 'zh_CN',
|
||||
'Traditional Chinese' => 'zh_TW',
|
||||
);
|
||||
return $locales;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
/**
|
||||
* @package: File Manager Advanced
|
||||
* @Class: elFinderVolumefma_local_filesystem
|
||||
* Custom LocalFileSystem driver with content search support
|
||||
* This extends elFinderVolumeLocalFileSystem without modifying library files
|
||||
*/
|
||||
if ( class_exists( 'elFinderVolumefma_local_filesystem' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (defined('FMAFILEPATH')) {
|
||||
require_once FMAFILEPATH . 'application/library/php/elFinderVolumeLocalFileSystem.class.php';
|
||||
} else {
|
||||
require_once dirname(__FILE__) . '/library/php/elFinderVolumeLocalFileSystem.class.php';
|
||||
}
|
||||
|
||||
class elFinderVolumefma_local_filesystem extends elFinderVolumeLocalFileSystem {
|
||||
|
||||
/**
|
||||
* Store tag for content search
|
||||
*/
|
||||
protected $contentSearchTag = '';
|
||||
|
||||
/**
|
||||
* Override search to handle content-based search via type parameter
|
||||
* We completely override parent search to ensure doSearch is called for content searches
|
||||
*/
|
||||
public function search($q, $mimes, $hash = null, $type = null) {
|
||||
$this->contentSearchTag = '';
|
||||
$tagFromHook = self::getContentSearchTag();
|
||||
|
||||
if (empty($tagFromHook) && strpos($q, '__CONTENT_SEARCH__:') === 0) {
|
||||
$tagFromHook = substr($q, strlen('__CONTENT_SEARCH__:'));
|
||||
$q = '';
|
||||
}
|
||||
if (empty($tagFromHook) && $type === 'SearchTag' && $q !== '' && $q !== 'CONTENTSEARCHPLACEHOLDER') {
|
||||
$tagFromHook = $q;
|
||||
}
|
||||
|
||||
$isContentSearch = ($type === 'SearchTag' || ($tagFromHook !== '' && $tagFromHook !== false && $tagFromHook !== null));
|
||||
|
||||
if ($isContentSearch) {
|
||||
$this->contentSearchTag = $tagFromHook;
|
||||
if ($q === '') {
|
||||
$q = 'CONTENTSEARCHPLACEHOLDER';
|
||||
}
|
||||
}
|
||||
|
||||
// Start of parent search logic (from elFinderVolumeDriver.class.php line 3160)
|
||||
$res = array();
|
||||
$matchMethod = empty($type) ? 'searchMatchName' : 'searchMatch' . $type;
|
||||
if (!method_exists($this, $matchMethod)) {
|
||||
$matchMethod = 'searchMatchName';
|
||||
}
|
||||
|
||||
$dir = null;
|
||||
if ($hash) {
|
||||
$dir = $this->decode($hash);
|
||||
$stat = $this->stat($dir);
|
||||
if (!$stat || $stat['mime'] !== 'directory' || !$stat['read']) {
|
||||
$q = '';
|
||||
}
|
||||
}
|
||||
if ($mimes && $this->onlyMimes) {
|
||||
$mimes = array_intersect($mimes, $this->onlyMimes);
|
||||
if (!$mimes) {
|
||||
$q = '';
|
||||
}
|
||||
}
|
||||
$this->searchStart = time();
|
||||
|
||||
$qs = preg_split('/"([^"]+)"| +/', $q, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
$query = $excludes = array();
|
||||
foreach ($qs as $_q) {
|
||||
$_q = trim($_q);
|
||||
if ($_q !== '') {
|
||||
if ($_q[0] === '-') {
|
||||
if (isset($_q[1])) {
|
||||
$excludes[] = substr($_q, 1);
|
||||
}
|
||||
} else {
|
||||
$query[] = $_q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For content search, ensure we don't return early even if query is empty
|
||||
if (!$query && !$isContentSearch) {
|
||||
$q = '';
|
||||
} else {
|
||||
if ($query) {
|
||||
$q = join(' ', $query);
|
||||
} else {
|
||||
// For content search, keep q as placeholder so doSearch is called
|
||||
$q = 'CONTENTSEARCHPLACEHOLDER';
|
||||
}
|
||||
$this->doSearchCurrentQuery = array(
|
||||
'q' => $q,
|
||||
'excludes' => $excludes,
|
||||
'matchMethod' => $matchMethod
|
||||
);
|
||||
// Set type for content search
|
||||
if ($isContentSearch) {
|
||||
$this->doSearchCurrentQuery['type'] = 'SearchTag';
|
||||
}
|
||||
}
|
||||
|
||||
// For content search, don't return early even if q is empty
|
||||
if (($q === '' && !$isContentSearch) || $this->commandDisabled('search')) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
// valided regex $this->options['searchExDirReg']
|
||||
if ($this->options['searchExDirReg']) {
|
||||
if (false === preg_match($this->options['searchExDirReg'], '')) {
|
||||
$this->options['searchExDirReg'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
// check the leaf root too
|
||||
if (!$mimes && (is_null($dir) || $dir == $this->root)) {
|
||||
$rootStat = $this->stat($this->root);
|
||||
if (!empty($rootStat['phash'])) {
|
||||
if ($isContentSearch || $this->stripos($rootStat['name'], $q) !== false) {
|
||||
$res = array($rootStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result = array_merge($res, $this->doSearch(is_null($dir) ? $this->root : $dir, $q, $mimes));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static storage for content search tag (set by bind hook)
|
||||
*/
|
||||
protected static $contentSearchTagStorage = '';
|
||||
|
||||
/**
|
||||
* Set content search tag (called by bind hook)
|
||||
*/
|
||||
public static function setContentSearchTag($tag) {
|
||||
self::$contentSearchTagStorage = $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content search tag
|
||||
*/
|
||||
public static function getContentSearchTag() {
|
||||
return self::$contentSearchTagStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override doSearch to implement content-based search
|
||||
*/
|
||||
protected function doSearch($path, $q, $mimes) {
|
||||
$result = array();
|
||||
$matchMethod = empty($this->doSearchCurrentQuery['matchMethod']) ? 'searchMatchName' : $this->doSearchCurrentQuery['matchMethod'];
|
||||
$timeout = $this->options['searchTimeout'] ? $this->searchStart + $this->options['searchTimeout'] : 0;
|
||||
if ($timeout && $timeout < time()) {
|
||||
$this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Get tag for content search - check instance property first, then static
|
||||
$tag = '';
|
||||
if (!empty($this->contentSearchTag)) {
|
||||
$tag = $this->contentSearchTag;
|
||||
} else {
|
||||
$tag = self::getContentSearchTag();
|
||||
}
|
||||
|
||||
// Check if this is content search
|
||||
// Primary indicator: type is set to SearchTag in doSearchCurrentQuery
|
||||
// Secondary: we have a tag stored
|
||||
$qInQuery = !empty($this->doSearchCurrentQuery['q']) ? $this->doSearchCurrentQuery['q'] : $q;
|
||||
// For content search, q might be 'CONTENTSEARCHPLACEHOLDER' or empty after parent processes it
|
||||
$isPlaceholderQ = ($qInQuery === 'CONTENTSEARCHPLACEHOLDER' || $qInQuery === '' || trim($qInQuery) === '');
|
||||
|
||||
// Check if type is already set in doSearchCurrentQuery
|
||||
$searchType = !empty($this->doSearchCurrentQuery['type']) ? $this->doSearchCurrentQuery['type'] : '';
|
||||
|
||||
// Determine if this is content search
|
||||
$hasTag = ($tag !== '' && $tag !== null && $tag !== false);
|
||||
$isContentSearch = false;
|
||||
|
||||
if ($hasTag) {
|
||||
// If we have a tag, check if this is content search
|
||||
if ($isPlaceholderQ || $searchType === 'SearchTag') {
|
||||
$isContentSearch = true;
|
||||
// Ensure type is set for recursive calls
|
||||
if (!isset($this->doSearchCurrentQuery['type'])) {
|
||||
$this->doSearchCurrentQuery['type'] = 'SearchTag';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->scandirCE($path) as $p) {
|
||||
elFinder::extendTimeLimit($this->options['searchTimeout'] + 30);
|
||||
|
||||
if ($timeout && ($this->error || $timeout < time())) {
|
||||
!$this->error && $this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
|
||||
break;
|
||||
}
|
||||
|
||||
$stat = $this->stat($p);
|
||||
|
||||
if (!$stat) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($stat['hidden']) || !$this->mimeAccepted($stat['mime'], $mimes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $stat['name'];
|
||||
|
||||
if ($this->doSearchCurrentQuery['excludes']) {
|
||||
foreach ($this->doSearchCurrentQuery['excludes'] as $exclude) {
|
||||
if ($this->stripos($name, $exclude) !== false) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For content search, skip directories completely (only search in files)
|
||||
if ($isContentSearch && $stat['mime'] === 'directory') {
|
||||
// Skip heavy/irrelevant dirs to avoid timeout
|
||||
$skipDirs = array('node_modules', 'vendor', '.git', '.svn', 'bower_components');
|
||||
if (in_array(strtolower($name), $skipDirs)) {
|
||||
continue;
|
||||
}
|
||||
// Still recurse into directories for content search, but don't include them in results
|
||||
if ($stat['read'] && !isset($stat['alias'])) {
|
||||
if (!$this->options['searchExDirReg'] || !preg_match($this->options['searchExDirReg'], $p)) {
|
||||
$result = array_merge($result, $this->doSearch($p, $q, $mimes));
|
||||
}
|
||||
}
|
||||
continue; // Skip directories in content search results
|
||||
}
|
||||
|
||||
// Check tag match (search inside file contents) for content search
|
||||
$tagMatch = true;
|
||||
if ($isContentSearch && $stat['mime'] !== 'directory' && is_readable($p)) {
|
||||
$tagMatch = false;
|
||||
|
||||
// Only search in text-based files
|
||||
$textMimes = array('text/', 'application/javascript', 'application/json', 'application/xml', 'application/x-php', 'text/x-php');
|
||||
$isTextFile = false;
|
||||
foreach ($textMimes as $textMime) {
|
||||
if (strpos($stat['mime'], $textMime) === 0) {
|
||||
$isTextFile = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Also check by extension
|
||||
$textExtensions = array('txt', 'php', 'js', 'css', 'html', 'htm', 'xml', 'json', 'md', 'log', 'sql', 'csv', 'ini', 'conf', 'config', 'yaml', 'yml');
|
||||
$ext = strtolower(pathinfo($p, PATHINFO_EXTENSION));
|
||||
if (!$isTextFile && in_array($ext, $textExtensions)) {
|
||||
$isTextFile = true;
|
||||
}
|
||||
|
||||
if ($isTextFile) {
|
||||
try {
|
||||
$maxRead = 2 * 1024 * 1024; // 2MB max read per file for content search
|
||||
$size = isset($stat['size']) ? (int) $stat['size'] : 0;
|
||||
if ($size > 0 && $size > $maxRead) {
|
||||
$fh = @fopen($p, 'rb');
|
||||
if ($fh) {
|
||||
$content = @fread($fh, $maxRead);
|
||||
@fclose($fh);
|
||||
} else {
|
||||
$content = false;
|
||||
}
|
||||
} else {
|
||||
$content = @file_get_contents($p);
|
||||
}
|
||||
if ($content !== false && $content !== '') {
|
||||
if (stripos($content, $tag) !== false) {
|
||||
$tagMatch = true;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$tagMatch = false;
|
||||
}
|
||||
} else {
|
||||
$tagMatch = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check name match - skip for content search
|
||||
$nameMatch = true;
|
||||
if (!$isContentSearch) {
|
||||
// Normal name-based search
|
||||
$nameMatch = ($q === '' || $this->$matchMethod($name, $q, $p) !== false);
|
||||
}
|
||||
// For content search, nameMatch is always true (we only care about content match)
|
||||
|
||||
// Include file if both name and tag match
|
||||
// For content search, only include files (not directories)
|
||||
if ((!$mimes || $stat['mime'] !== 'directory') && $nameMatch && $tagMatch) {
|
||||
$stat['path'] = $this->path($stat['hash']);
|
||||
if ($this->URL && !isset($stat['url'])) {
|
||||
$path = str_replace($this->separator, '/', substr($p, strlen($this->root) + 1));
|
||||
if ($this->encoding) {
|
||||
$path = str_replace('%2F', '/', rawurlencode($this->convEncIn($path, true)));
|
||||
} else {
|
||||
$path = str_replace('%2F', '/', rawurlencode($path));
|
||||
}
|
||||
$stat['url'] = $this->URL . $path;
|
||||
}
|
||||
|
||||
$result[] = $stat;
|
||||
}
|
||||
|
||||
// Recurse into directories for non-content searches
|
||||
// (For content searches, we already handled recursion above)
|
||||
if (!$isContentSearch && $stat['mime'] == 'directory' && $stat['read'] && !isset($stat['alias'])) {
|
||||
if (!$this->options['searchExDirReg'] || !preg_match($this->options['searchExDirReg'], $p)) {
|
||||
$result = array_merge($result, $this->doSearch($p, $q, $mimes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,467 @@
|
||||
<?php
|
||||
/**
|
||||
* File Manager Advanced Main Class
|
||||
*
|
||||
* @package: File Manager Advanced
|
||||
* @Class: fma_main
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (class_exists('class_fma_main')) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main Class
|
||||
*/
|
||||
class class_fma_main
|
||||
{
|
||||
/**
|
||||
* Settings
|
||||
*
|
||||
* @var false|mixed|null $settings Plugin settings.
|
||||
*/
|
||||
public $settings;
|
||||
|
||||
/**
|
||||
* SMTP Recommendation instance
|
||||
*/
|
||||
public $recommend_smtp;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
add_action('admin_menu', array(&$this, 'fma_menus'));
|
||||
add_action('admin_enqueue_scripts', array(&$this, 'fma_scripts'));
|
||||
add_action('wp_ajax_fma_load_fma_ui', array(&$this, 'fma_load_fma_ui'));
|
||||
add_action('wp_ajax_fma_review_ajax', array($this, 'fma_review_ajax'));
|
||||
add_action('wp_ajax_fma_save_php_file', array($this, 'fma_save_php_file'));
|
||||
add_action('wp_ajax_fma_debug_php', array($this, 'fma_debug_php'));
|
||||
$this->settings = get_option('fmaoptions');
|
||||
|
||||
add_action('admin_init', array($this, 'admin_init'));
|
||||
// Hook into WordPress to handle slashes in POST data for elFinder
|
||||
add_action('init', array($this, 'handle_elfinder_post_data'));
|
||||
|
||||
// Initialize SMTP recommendation
|
||||
$this->init_smtp_recommendation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Menus
|
||||
*/
|
||||
public function fma_menus()
|
||||
{
|
||||
include 'class_fma_admin_menus.php';
|
||||
$fma_menus = new class_fma_admin_menus();
|
||||
$fma_menus->load_menus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load File Manager UI
|
||||
*/
|
||||
public function fma_load_fma_ui()
|
||||
{
|
||||
include 'class_fma_connector.php';
|
||||
$fma_connector = new class_fma_connector();
|
||||
if (wp_verify_nonce($_REQUEST['_fmakey'], 'fmaskey')) {
|
||||
$fma_connector->fma_local_file_system();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Scripts
|
||||
*
|
||||
* @param string $hook The current admin page.
|
||||
*/
|
||||
public function fma_scripts($hook)
|
||||
{
|
||||
$locale = isset($this->settings['fma_locale']) ? sanitize_file_name($this->settings['fma_locale']) : 'en';
|
||||
$display_ui_options = isset($this->settings['display_ui_options']) ? $this->settings['display_ui_options'] : FMA_UI;
|
||||
$cm_theme = isset($this->settings['fma_cm_theme']) ? $this->settings['fma_cm_theme'] : 'default';
|
||||
$library_url = FMA_PLUGIN_URL . 'application/library/';
|
||||
$hide_path = false;
|
||||
if (isset($this->settings['hide_path']) && 1 === absint($this->settings['hide_path'])) {
|
||||
$hide_path = true;
|
||||
}
|
||||
|
||||
if ('toplevel_page_file_manager_advanced_ui' === $hook) {
|
||||
if (isset($_GET['page']) && 'file_manager_advanced_ui' === sanitize_text_field(wp_unslash($_GET['page']))) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
wp_enqueue_style('elfinder.jquery-ui', $library_url . 'jquery/jquery-ui.min.css', array(), FMA_VERSION, 'all');
|
||||
wp_enqueue_style('elfinder', $library_url . 'css/elfinder.min.css', array(), FMA_VERSION, 'all');
|
||||
wp_enqueue_style('elfinder.theme', $library_url . 'css/theme.css', array(), FMA_VERSION, 'all');
|
||||
wp_enqueue_style('codemirror', $library_url . 'codemirror/lib/codemirror.css', array(), FMA_VERSION, 'all');
|
||||
|
||||
if (isset($this->settings['fma_theme']) && in_array($this->settings['fma_theme'], array('dark', 'grey', 'windows10', 'bootstrap', 'mono', 'm-light', 'moono'), true)) {
|
||||
wp_enqueue_style('elfinder.preview', $library_url . 'themes/' . $this->settings['fma_theme'] . '/css/theme.css', array(), FMA_VERSION, 'all');
|
||||
}
|
||||
|
||||
wp_enqueue_style('elfinder.styles', FMA_PLUGIN_URL . 'application/assets/css/custom_style_filemanager_advanced.css', array(), FMA_VERSION, 'all');
|
||||
|
||||
wp_enqueue_script('elfinder', $library_url . 'js/elfinder.min.js', array('jquery', 'jquery-ui-core', 'jquery-ui-selectable', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-resizable', 'jquery-ui-dialog', 'jquery-ui-slider', 'jquery-ui-tabs'), FMA_VERSION, true);
|
||||
wp_enqueue_script('codemirror', $library_url . 'codemirror/lib/codemirror.js', array(), FMA_VERSION, true);
|
||||
wp_enqueue_script('codemirror.htmlmixed', $library_url . 'codemirror/mode/htmlmixed/htmlmixed.js', array(), FMA_VERSION, true);
|
||||
wp_enqueue_script('codemirror.xml', $library_url . 'codemirror/mode/xml/xml.js', array(), FMA_VERSION, true);
|
||||
wp_enqueue_script('codemirror.css', $library_url . 'codemirror/mode/css/css.js', array(), FMA_VERSION, true);
|
||||
wp_enqueue_script('codemirror.javascript', $library_url . 'codemirror/mode/javascript/javascript.js', array(), FMA_VERSION, true);
|
||||
wp_enqueue_script('codemirror.clike', $library_url . 'codemirror/mode/clike/clike.js', array(), FMA_VERSION, true);
|
||||
wp_enqueue_script('codemirror.php', $library_url . 'codemirror/mode/php/php.js', array(), FMA_VERSION, true);
|
||||
|
||||
if ('en' !== $locale) {
|
||||
wp_enqueue_script('elfinder.language', $library_url . sprintf('js/i18n/elfinder.%s.js', $locale), array('elfinder'), FMA_VERSION, true);
|
||||
}
|
||||
|
||||
if ('default' !== $cm_theme) {
|
||||
wp_enqueue_style('codemirror.theme', $library_url . 'codemirror/theme/' . $cm_theme . '.css', array(), FMA_VERSION, 'all');
|
||||
}
|
||||
|
||||
wp_enqueue_script('fma-elfinder-commands', FMA_PLUGIN_URL . 'application/assets/js/fma-elfinder-commands.js', array('jquery', 'elfinder'), FMA_VERSION, true);
|
||||
wp_enqueue_script('elfinder.script', FMA_PLUGIN_URL . 'application/assets/js/elfinder_script.js', array('jquery', 'fma-elfinder-commands'), FMA_VERSION, true);
|
||||
wp_localize_script(
|
||||
'elfinder.script',
|
||||
'afm_object',
|
||||
array(
|
||||
'ajaxurl' => admin_url('admin-ajax.php'),
|
||||
'nonce' => wp_create_nonce('fmaskey'),
|
||||
'locale' => $locale,
|
||||
'ui' => $display_ui_options,
|
||||
'cm_theme' => $cm_theme,
|
||||
'hide_path' => $hide_path,
|
||||
'plugin_url' => FMA_PLUGIN_URL,
|
||||
'debug_enabled' => isset($this->settings['fma_debug_enabled']) ? $this->settings['fma_debug_enabled'] : '0',
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
wp_register_style('afm-jquery.select2', FMA_PLUGIN_URL . 'application/assets/css/select2/jquery.select2.min.css', array(), FMA_VERSION, 'all');
|
||||
wp_register_script('afm-jquery.select2', FMA_PLUGIN_URL . 'application/assets/js/select2/jquery.select2.min.js', array('jquery'), FMA_VERSION, true);
|
||||
|
||||
if (in_array($hook, array('file-manager_page_file_manager_advanced_controls', 'file-manager_page_file_manager_advanced_shortcodes', 'file-manager_page_afmp-adminer', 'file-manager_page_afmp-dropbox', 'file-manager_page_afmp-googledrive', 'file-manager_page_afmp-googlecloud', 'file-manager_page_afmp-github', 'toplevel_page_file_manager_advanced_ui', 'file-manager_page_afmp-file-logs', 'file-manager_page_afmp-onedrive', 'file-manager_page_afmp-aws', 'file-manager_page_afm-integrations-pro'), true)) {
|
||||
wp_enqueue_style('afm-admin', FMA_PLUGIN_URL . 'application/assets/css/afm-styles.css', array('afm-jquery.select2'), FMA_VERSION, 'all');
|
||||
wp_enqueue_script('afm-admin', FMA_PLUGIN_URL . 'application/assets/js/afm-scripts.js', array('afm-jquery.select2'), FMA_VERSION, true);
|
||||
wp_localize_script(
|
||||
'afm-admin',
|
||||
'afmAdmin',
|
||||
array(
|
||||
'assetsURL' => FMA_PLUGIN_URL . 'application/assets/',
|
||||
'jsonURL' => rest_url(),
|
||||
),
|
||||
);
|
||||
// Enqueue SMTP scripts if we are on the settings page
|
||||
if ($hook === 'file-manager_page_file_manager_advanced_controls' && $this->recommend_smtp) {
|
||||
$this->recommend_smtp->admin_enqueue_scripts();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Code Mirror Themes
|
||||
*/
|
||||
public static function cm_themes()
|
||||
{
|
||||
$cm_themes_dir = FMA_CM_THEMES_PATH;
|
||||
$cm_themes = [];
|
||||
$cm_themes['default'] = array(
|
||||
'title' => 'default',
|
||||
'pro' => false,
|
||||
);
|
||||
|
||||
$free_themes = array('3024-day', '3024-night', 'base16-dark', 'base16-light', 'downtown-light');
|
||||
foreach (glob($cm_themes_dir . '/*.css') as $file) {
|
||||
$bn = basename($file, ".css");
|
||||
$args = array(
|
||||
'title' => $bn,
|
||||
'pro' => true,
|
||||
);
|
||||
if (in_array($bn, $free_themes, true)) {
|
||||
$args['pro'] = false;
|
||||
}
|
||||
$cm_themes[$bn] = $args;
|
||||
}
|
||||
|
||||
usort(
|
||||
$cm_themes,
|
||||
function ($a, $b) {
|
||||
if ($a['pro'] === $b['pro']) {
|
||||
return 0;
|
||||
}
|
||||
return $a['pro'] ? 1 : -1;
|
||||
}
|
||||
);
|
||||
|
||||
return $cm_themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Review Ajax
|
||||
*/
|
||||
public function fma_review_ajax()
|
||||
{
|
||||
$nonce = $_REQUEST['nonce'];
|
||||
if (!wp_verify_nonce($nonce, 'afm_review')) {
|
||||
die(__('Security check', 'file-manager-advanced'));
|
||||
} else {
|
||||
$task = sanitize_text_field($_POST['task']);
|
||||
$done = update_option('fma_hide_review_section', $task);
|
||||
if ($done) {
|
||||
echo '1';
|
||||
} else {
|
||||
echo '0';
|
||||
}
|
||||
die;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin Init
|
||||
*
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public function admin_init()
|
||||
{
|
||||
$is_pro_version = get_option('active_plugins', array());
|
||||
$is_pro_active = false;
|
||||
foreach ($is_pro_version as $plugin_file) {
|
||||
if (is_string($plugin_file) && preg_match('#/file-manager-advanced-shortcode\.php$#', $plugin_file)) {
|
||||
$is_pro_active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($is_pro_active) {
|
||||
require_once FMAFILEPATH . 'application/logs/class-filelogs.php';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PHP Debug Analysis Ajax
|
||||
*/
|
||||
public function fma_debug_php()
|
||||
{
|
||||
// Check nonce for security
|
||||
if (!wp_verify_nonce($_POST['nonce'], 'fmaskey')) {
|
||||
wp_die(__('Security check failed', 'file-manager-advanced'));
|
||||
}
|
||||
|
||||
// Get the PHP code from POST data
|
||||
$php_code = wp_unslash($_POST['php_code']);
|
||||
$filename = sanitize_text_field($_POST['filename']);
|
||||
|
||||
// Load the debug analyzer
|
||||
require_once FMAFILEPATH . 'application/library/php-parser/src/FMA_PhpDebugAnalyzer.php';
|
||||
|
||||
// Analyze PHP code for debug information
|
||||
$debug_result = FMA_PhpDebugAnalyzer::analyze($php_code, $filename);
|
||||
|
||||
// Return JSON response
|
||||
wp_send_json($debug_result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save PHP file with proper unescaping
|
||||
*/
|
||||
public function fma_save_php_file()
|
||||
{
|
||||
// Check nonce for security
|
||||
if (!wp_verify_nonce($_POST['nonce'], 'fmaskey')) {
|
||||
wp_send_json_error(array('message' => __('Security check failed', 'file-manager-advanced')));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the PHP code and file info from POST data
|
||||
$php_code = wp_unslash($_POST['php_code']);
|
||||
$file_hash = sanitize_text_field($_POST['file_hash']);
|
||||
$filename = sanitize_text_field(wp_unslash($_POST['filename']));
|
||||
|
||||
// Skip validation since this is called when user chooses "Save Anyway"
|
||||
// The validation was already done and user explicitly chose to save with errors
|
||||
|
||||
try {
|
||||
// Store original POST data
|
||||
$original_post = $_POST;
|
||||
|
||||
// Set up POST data for elFinder save operation
|
||||
$_POST = array(
|
||||
'cmd' => 'put',
|
||||
'target' => $file_hash,
|
||||
// Pass raw content: elFinder does not stripslashes on modern PHP; wp_slash() corrupts \" sequences.
|
||||
'content' => $php_code,
|
||||
'action' => 'fma_load_fma_ui',
|
||||
'_fmakey' => wp_create_nonce('fmaskey')
|
||||
);
|
||||
|
||||
// Use elFinder connector to save the file
|
||||
if (!class_exists('class_fma_connector')) {
|
||||
include_once 'class_fma_connector.php';
|
||||
}
|
||||
|
||||
if (class_exists('class_fma_connector')) {
|
||||
$fma_connector = new class_fma_connector();
|
||||
|
||||
// Capture elFinder output
|
||||
ob_start();
|
||||
$fma_connector->fma_local_file_system();
|
||||
$elfinder_response = ob_get_clean();
|
||||
|
||||
// Restore original POST data
|
||||
$_POST = $original_post;
|
||||
|
||||
// Parse elFinder response
|
||||
$response_data = json_decode($elfinder_response, true);
|
||||
|
||||
if ($response_data && isset($response_data['changed']) && !empty($response_data['changed'])) {
|
||||
wp_send_json_success(array(
|
||||
'message' => __('File saved successfully', 'file-manager-advanced'),
|
||||
'elfinder_response' => $response_data
|
||||
));
|
||||
} else if ($response_data && !isset($response_data['error'])) {
|
||||
// Sometimes elFinder doesn't return 'changed' but save is successful
|
||||
wp_send_json_success(array(
|
||||
'message' => __('File saved successfully', 'file-manager-advanced'),
|
||||
'elfinder_response' => $response_data
|
||||
));
|
||||
} else {
|
||||
$error_message = '';
|
||||
if ($response_data && isset($response_data['error'])) {
|
||||
$error_message = $response_data['error'];
|
||||
} else {
|
||||
$error_message = __('Failed to save file through elFinder', 'file-manager-advanced');
|
||||
}
|
||||
|
||||
wp_send_json_error(array(
|
||||
'message' => $error_message,
|
||||
'elfinder_response' => $elfinder_response
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// Restore original POST data
|
||||
$_POST = $original_post;
|
||||
|
||||
wp_send_json_error(array(
|
||||
'message' => __('elFinder connector class not found', 'file-manager-advanced')
|
||||
));
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
// Restore original POST data in case of exception
|
||||
$_POST = $original_post;
|
||||
|
||||
wp_send_json_error(array(
|
||||
'message' => sprintf(__('Error saving file: %s', 'file-manager-advanced'), $e->getMessage()),
|
||||
'exception' => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle elFinder POST data to remove WordPress slashes
|
||||
*/
|
||||
public function handle_elfinder_post_data()
|
||||
{
|
||||
// Only process on admin AJAX requests for our file manager
|
||||
if (!is_admin() || !defined('DOING_AJAX') || !DOING_AJAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is our elFinder request
|
||||
if (!isset($_POST['action']) || $_POST['action'] !== 'fma_load_fma_ui') {
|
||||
return;
|
||||
}
|
||||
|
||||
// WordPress slashes $_POST; elFinder only stripslashes when magic_quotes_gpc (removed in PHP 5.4+).
|
||||
if (isset($_POST['cmd']) && 'put' === $_POST['cmd'] && isset($_POST['content']) && is_string($_POST['content'])) {
|
||||
$_POST['content'] = wp_unslash($_POST['content']);
|
||||
$_REQUEST['content'] = $_POST['content'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize SMTP recommendation using universal system
|
||||
* @since 6.7.3
|
||||
*/
|
||||
private function init_smtp_recommendation()
|
||||
{
|
||||
require_once FMAFILEPATH . 'application/post-smtp-notice/recommend-post-smtp-loader.php';
|
||||
|
||||
// Initialize SMTP recommendation without parent menu (to hide submenu)
|
||||
$this->recommend_smtp = recommend_smtp_loader(
|
||||
'fma', // Unique plugin identifier
|
||||
'file-manager-advanced', // Plugin slug
|
||||
true, // Show admin notice
|
||||
false, // Parent menu (false = no submenu)
|
||||
'png' // Format
|
||||
);
|
||||
|
||||
if (!function_exists('is_plugin_active')) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
$smtp_plugins = array(
|
||||
'post-smtp/postman-smtp.php',
|
||||
'wp-mail-smtp/wp_mail_smtp.php',
|
||||
'wp-mail-smtp-pro/wp_mail_smtp_pro.php',
|
||||
'easy-wp-smtp/easy-wp-smtp.php',
|
||||
'fluent-smtp/fluent-smtp.php',
|
||||
'gosmtp/gosmtp.php',
|
||||
'smtp-mailer/smtp-mailer.php',
|
||||
'suremails/suremails.php',
|
||||
'mailin/mailin.php',
|
||||
'site-mailer/site-mailer.php',
|
||||
'wp-smtp/wp-smtp.php'
|
||||
);
|
||||
|
||||
$smtp_active = false;
|
||||
foreach ($smtp_plugins as $plugin) {
|
||||
if (is_plugin_active($plugin)) {
|
||||
$smtp_active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only add SMTP tab if no SMTP plugin is active
|
||||
if (!$smtp_active) {
|
||||
// Add SMTP tab to settings with a high priority to ensure it's always last
|
||||
add_filter('fma__settings_tabs', array($this, 'fma_settings_smtp_tab'), 999);
|
||||
// Add content for SMTP tab
|
||||
add_action('fma__settings_tab_smtp_content', array($this, 'fma_settings_smtp_content'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add SMTP tab to settings
|
||||
* @param array $tabs
|
||||
* @return array
|
||||
*/
|
||||
public function fma_settings_smtp_tab($tabs)
|
||||
{
|
||||
$tabs['smtp'] = array(
|
||||
'title' => __('SMTP', 'file-manager-advanced') . ' <span style="background: #d63638; color: #fff; font-size: 9px; padding: 2px 6px; border-radius: 10px; margin-left: 5px; vertical-align: middle;">FREE</span>',
|
||||
'slug' => 'smtp',
|
||||
'icon' => '<i class="dashicons dashicons-email-alt"></i>',
|
||||
);
|
||||
return $tabs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display SMTP tab content
|
||||
*/
|
||||
public function fma_settings_smtp_content()
|
||||
{
|
||||
if ($this->recommend_smtp) {
|
||||
$this->recommend_smtp->recommend_post_smtp_submenu();
|
||||
}
|
||||
}
|
||||
|
||||
public static function has_pro()
|
||||
{
|
||||
$has_pro = apply_filters('fma__has_pro', false);
|
||||
return $has_pro;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,492 @@
|
||||
<?php
|
||||
/**
|
||||
* FMA Pure PHP Validator
|
||||
*
|
||||
* Pure PHP syntax validation without any exec functions
|
||||
* Uses nikic/php-parser for accurate validation
|
||||
*
|
||||
* @package Advanced File Manager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'FMA_Pure_PHP_Validator' ) ) :
|
||||
|
||||
class FMA_Pure_PHP_Validator {
|
||||
|
||||
private static $instance = null;
|
||||
private $parser = null;
|
||||
|
||||
public static function get_instance() {
|
||||
if ( null === self::$instance ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
$this->init_parser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize PHP Parser
|
||||
*/
|
||||
private function init_parser() {
|
||||
// Load Composer autoloader
|
||||
$autoload_path = dirname( __FILE__ ) . '/library/vendor/autoload.php';
|
||||
if ( file_exists( $autoload_path ) ) {
|
||||
require_once $autoload_path;
|
||||
}
|
||||
|
||||
// Try to use nikic/php-parser if available
|
||||
if ( class_exists( 'PhpParser\\ParserFactory' ) ) {
|
||||
try {
|
||||
$factory = new \PhpParser\ParserFactory();
|
||||
$this->parser = $factory->createForHostVersion();
|
||||
} catch ( Exception $e ) {
|
||||
$this->parser = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate PHP syntax using pure PHP methods
|
||||
*/
|
||||
public function validate_syntax( $php_code ) {
|
||||
$result = array(
|
||||
'valid' => false,
|
||||
'errors' => array(),
|
||||
'message' => '',
|
||||
'php_version' => 'PHP ' . PHP_VERSION,
|
||||
'execution_time' => 0
|
||||
);
|
||||
|
||||
$start_time = microtime( true );
|
||||
|
||||
try {
|
||||
// Method 1: Try nikic/php-parser if available
|
||||
if ( $this->parser !== null ) {
|
||||
$parser_result = $this->validate_with_parser( $php_code );
|
||||
if ( $parser_result['valid'] || ! empty( $parser_result['errors'] ) ) {
|
||||
$result = $parser_result;
|
||||
$result['execution_time'] = round( ( microtime( true ) - $start_time ) * 1000, 2 );
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// Method 2: Enhanced basic syntax check
|
||||
$result = $this->validate_with_enhanced_check( $php_code );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
// If all methods fail, fall back to basic check
|
||||
$result = $this->validate_with_enhanced_check( $php_code );
|
||||
}
|
||||
|
||||
$result['execution_time'] = round( ( microtime( true ) - $start_time ) * 1000, 2 );
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate using nikic/php-parser
|
||||
*/
|
||||
private function validate_with_parser( $php_code ) {
|
||||
$result = array(
|
||||
'valid' => false,
|
||||
'errors' => array(),
|
||||
'message' => '',
|
||||
'php_version' => 'PHP ' . PHP_VERSION,
|
||||
'execution_time' => 0
|
||||
);
|
||||
|
||||
try {
|
||||
// Ensure code has proper PHP tags
|
||||
if ( strpos( $php_code, '<?php' ) === false && strpos( $php_code, '<?=' ) === false ) {
|
||||
$php_code = '<?php' . "\n" . $php_code;
|
||||
}
|
||||
|
||||
$stmts = $this->parser->parse( $php_code );
|
||||
|
||||
if ( $stmts === null ) {
|
||||
$result['valid'] = false;
|
||||
$result['message'] = 'PHP syntax errors found';
|
||||
$result['errors'][] = array(
|
||||
'type' => 'parse_error',
|
||||
'message' => 'Unable to parse PHP code',
|
||||
'file' => 'unknown',
|
||||
'line' => 0,
|
||||
'severity' => 'error'
|
||||
);
|
||||
} else {
|
||||
$result['valid'] = true;
|
||||
$result['message'] = 'PHP syntax is valid';
|
||||
$result['errors'] = array();
|
||||
}
|
||||
|
||||
} catch ( \PhpParser\Error $e ) {
|
||||
$result['valid'] = false;
|
||||
$result['message'] = 'PHP syntax errors found';
|
||||
$result['errors'][] = array(
|
||||
'type' => 'parse_error',
|
||||
'message' => $e->getMessage(),
|
||||
'file' => 'unknown',
|
||||
'line' => $e->getStartLine(),
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced basic syntax check without exec functions
|
||||
*/
|
||||
private function validate_with_enhanced_check( $php_code ) {
|
||||
$result = array(
|
||||
'valid' => false,
|
||||
'errors' => array(),
|
||||
'message' => '',
|
||||
'php_version' => 'PHP ' . PHP_VERSION,
|
||||
'execution_time' => 0
|
||||
);
|
||||
|
||||
// Ensure code has proper PHP tags
|
||||
if ( strpos( $php_code, '<?php' ) === false && strpos( $php_code, '<?=' ) === false ) {
|
||||
$php_code = '<?php' . "\n" . $php_code;
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
|
||||
// Method 1: Use token_get_all
|
||||
$tokens = @token_get_all( $php_code );
|
||||
if ( $tokens === false ) {
|
||||
$errors[] = array(
|
||||
'type' => 'syntax_error',
|
||||
'message' => 'Invalid PHP syntax detected',
|
||||
'file' => 'unknown',
|
||||
'line' => 0,
|
||||
'severity' => 'error'
|
||||
);
|
||||
} else {
|
||||
// Method 2: Enhanced syntax analysis
|
||||
$syntax_errors = $this->analyze_syntax( $php_code );
|
||||
$errors = array_merge( $errors, $syntax_errors );
|
||||
}
|
||||
|
||||
// Method 3: Try eval in safe way (last resort)
|
||||
if ( empty( $errors ) ) {
|
||||
$eval_errors = $this->safe_eval_check( $php_code );
|
||||
$errors = array_merge( $errors, $eval_errors );
|
||||
}
|
||||
|
||||
if ( empty( $errors ) ) {
|
||||
$result['valid'] = true;
|
||||
$result['message'] = 'PHP syntax is valid';
|
||||
$result['errors'] = array();
|
||||
} else {
|
||||
$result['valid'] = false;
|
||||
$result['message'] = 'PHP syntax errors found';
|
||||
$result['errors'] = $errors;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced syntax analysis
|
||||
*/
|
||||
private function analyze_syntax( $php_code ) {
|
||||
$errors = array();
|
||||
$lines = explode( "\n", $php_code );
|
||||
$line_number = 0;
|
||||
|
||||
foreach ( $lines as $line ) {
|
||||
$line_number++;
|
||||
$trimmed = trim( $line );
|
||||
|
||||
// Skip empty lines and comments
|
||||
if ( empty( $trimmed ) || strpos( $trimmed, '//' ) === 0 || strpos( $trimmed, '#' ) === 0 || strpos( $trimmed, '/*' ) === 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for unclosed strings
|
||||
if ( $this->has_unclosed_string( $line ) ) {
|
||||
$errors[] = array(
|
||||
'type' => 'syntax_error',
|
||||
'message' => 'Unclosed string',
|
||||
'file' => 'unknown',
|
||||
'line' => $line_number,
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
// Check for unclosed brackets
|
||||
if ( $this->has_unclosed_brackets( $line ) ) {
|
||||
$errors[] = array(
|
||||
'type' => 'syntax_error',
|
||||
'message' => 'Unclosed brackets',
|
||||
'file' => 'unknown',
|
||||
'line' => $line_number,
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
// Check for common syntax errors
|
||||
$common_errors = $this->check_common_syntax_errors( $line, $line_number );
|
||||
$errors = array_merge( $errors, $common_errors );
|
||||
}
|
||||
|
||||
// Check overall bracket balance
|
||||
$bracket_balance = $this->check_bracket_balance( $php_code );
|
||||
if ( $bracket_balance !== 0 ) {
|
||||
$errors[] = array(
|
||||
'type' => 'syntax_error',
|
||||
'message' => 'Unbalanced brackets',
|
||||
'file' => 'unknown',
|
||||
'line' => count( $lines ),
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check common syntax errors
|
||||
*/
|
||||
private function check_common_syntax_errors( $line, $line_number ) {
|
||||
$errors = array();
|
||||
$trimmed = trim( $line );
|
||||
|
||||
// Skip empty lines, comments, and PHP tags
|
||||
if ( empty( $trimmed ) ||
|
||||
strpos( $trimmed, '//' ) === 0 ||
|
||||
strpos( $trimmed, '#' ) === 0 ||
|
||||
strpos( $trimmed, '/*' ) === 0 ||
|
||||
strpos( $trimmed, '*/' ) === 0 ||
|
||||
strpos( $trimmed, '<?php' ) === 0 ||
|
||||
strpos( $trimmed, '<?=' ) === 0 ||
|
||||
strpos( $trimmed, '?>' ) === 0 ) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Skip control structures that don't need semicolons
|
||||
if ( preg_match( '/^(if|else|for|while|foreach|function|class|interface|trait|switch|case|default|try|catch|finally)\s*[\(:]?/', $trimmed ) ||
|
||||
preg_match( '/^[\s]*[{}][\s]*$/', $trimmed ) ||
|
||||
preg_match( '/^[\s]*\/\//', $trimmed ) ||
|
||||
preg_match( '/^[\s]*\/\*/', $trimmed ) ||
|
||||
preg_match( '/^[\s]*\*/', $trimmed ) ) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Check for missing semicolons only on statements that should have them
|
||||
if ( preg_match( '/^[^=]*[^;{}]\s*$/', $trimmed ) &&
|
||||
! preg_match( '/^[\s]*[{}][\s]*$/', $trimmed ) &&
|
||||
! preg_match( '/^[\s]*\/\//', $trimmed ) &&
|
||||
! preg_match( '/^[\s]*\/\*/', $trimmed ) &&
|
||||
! preg_match( '/^[\s]*\*/', $trimmed ) ) {
|
||||
|
||||
// More sophisticated check - only flag if it looks like a statement
|
||||
if ( preg_match( '/^(echo|print|return|break|continue|throw|include|require|unset|isset|empty)\s+/', $trimmed ) ||
|
||||
preg_match( '/\$[a-zA-Z_][a-zA-Z0-9_]*\s*[=]/', $trimmed ) ||
|
||||
preg_match( '/[a-zA-Z_][a-zA-Z0-9_]*\s*\(/', $trimmed ) ||
|
||||
preg_match( '/^\s*(private|public|protected|var|const)\s+/', $trimmed ) ) {
|
||||
$errors[] = array(
|
||||
'type' => 'syntax_error',
|
||||
'message' => 'Missing semicolon',
|
||||
'file' => 'unknown',
|
||||
'line' => $line_number,
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for unclosed parentheses
|
||||
$open_parens = substr_count( $line, '(' );
|
||||
$close_parens = substr_count( $line, ')' );
|
||||
if ( $open_parens !== $close_parens ) {
|
||||
$errors[] = array(
|
||||
'type' => 'syntax_error',
|
||||
'message' => 'Unclosed parentheses',
|
||||
'file' => 'unknown',
|
||||
'line' => $line_number,
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe eval check (last resort)
|
||||
*/
|
||||
private function safe_eval_check( $php_code ) {
|
||||
$errors = array();
|
||||
|
||||
// Only try eval if it's safe and enabled
|
||||
if ( function_exists( 'eval' ) && ! in_array( 'eval', explode( ',', ini_get( 'disable_functions' ) ) ) ) {
|
||||
// Create a safe wrapper
|
||||
$safe_code = '<?php ' . $php_code;
|
||||
|
||||
// Use output buffering to catch any errors
|
||||
ob_start();
|
||||
$old_error_handler = set_error_handler( function( $severity, $message, $file, $line ) use ( &$errors ) {
|
||||
$errors[] = array(
|
||||
'type' => 'eval_error',
|
||||
'message' => $message,
|
||||
'file' => 'unknown',
|
||||
'line' => $line,
|
||||
'severity' => 'error'
|
||||
);
|
||||
return true; // Don't execute PHP internal error handler
|
||||
});
|
||||
|
||||
try {
|
||||
@eval( $safe_code );
|
||||
} catch ( ParseError $e ) {
|
||||
$errors[] = array(
|
||||
'type' => 'parse_error',
|
||||
'message' => $e->getMessage(),
|
||||
'file' => 'unknown',
|
||||
'line' => $e->getLine(),
|
||||
'severity' => 'error'
|
||||
);
|
||||
} catch ( Error $e ) {
|
||||
$errors[] = array(
|
||||
'type' => 'fatal_error',
|
||||
'message' => $e->getMessage(),
|
||||
'file' => 'unknown',
|
||||
'line' => $e->getLine(),
|
||||
'severity' => 'error'
|
||||
);
|
||||
}
|
||||
|
||||
ob_end_clean();
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if line has unclosed string
|
||||
*/
|
||||
private function has_unclosed_string( $line ) {
|
||||
$in_string = false;
|
||||
$string_char = '';
|
||||
$escaped = false;
|
||||
|
||||
for ( $i = 0; $i < strlen( $line ); $i++ ) {
|
||||
$char = $line[$i];
|
||||
|
||||
if ( $escaped ) {
|
||||
$escaped = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $char === '\\' ) {
|
||||
$escaped = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ( $char === '"' || $char === "'" ) && ! $in_string ) {
|
||||
$in_string = true;
|
||||
$string_char = $char;
|
||||
} elseif ( $char === $string_char && $in_string ) {
|
||||
$in_string = false;
|
||||
$string_char = '';
|
||||
}
|
||||
}
|
||||
|
||||
return $in_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if line has unclosed brackets
|
||||
*/
|
||||
private function has_unclosed_brackets( $line ) {
|
||||
// Don't check single lines for bracket balance - this is handled globally
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check overall bracket balance
|
||||
*/
|
||||
private function check_bracket_balance( $code ) {
|
||||
$balance = 0;
|
||||
$in_string = false;
|
||||
$string_char = '';
|
||||
$escaped = false;
|
||||
|
||||
for ( $i = 0; $i < strlen( $code ); $i++ ) {
|
||||
$char = $code[$i];
|
||||
|
||||
if ( $escaped ) {
|
||||
$escaped = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $char === '\\' ) {
|
||||
$escaped = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ( $char === '"' || $char === "'" ) && ! $in_string ) {
|
||||
$in_string = true;
|
||||
$string_char = $char;
|
||||
} elseif ( $char === $string_char && $in_string ) {
|
||||
$in_string = false;
|
||||
$string_char = '';
|
||||
} elseif ( ! $in_string ) {
|
||||
switch ( $char ) {
|
||||
case '{':
|
||||
case '(':
|
||||
case '[':
|
||||
$balance++;
|
||||
break;
|
||||
case '}':
|
||||
case ')':
|
||||
case ']':
|
||||
$balance--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if validation is available
|
||||
*/
|
||||
public function is_available() {
|
||||
try {
|
||||
$test_code = '<?php echo "test";';
|
||||
$result = $this->validate_syntax( $test_code );
|
||||
return $result['valid'];
|
||||
} catch ( Exception $e ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get validator info
|
||||
*/
|
||||
public function get_validator_info() {
|
||||
return array(
|
||||
'type' => 'Pure PHP Validator',
|
||||
'parser_available' => $this->parser !== null,
|
||||
'php_version' => PHP_VERSION,
|
||||
'exec_functions_required' => false,
|
||||
'features' => array(
|
||||
'Enhanced syntax checking',
|
||||
'No exec functions required',
|
||||
'Multiple validation methods',
|
||||
'Detailed error reporting'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/*
|
||||
@package: File Manager Advanced
|
||||
@Class: class_fma_shortcode
|
||||
*/
|
||||
if ( !defined('fma_file') ) {
|
||||
define('fma_file',__FILE__);
|
||||
}
|
||||
class class_fma_shortcode {
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder connector helpers (admin + frontend blocks).
|
||||
*
|
||||
* @package File_Manager_Advanced
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!function_exists('fma_create_elfinder_connector')) {
|
||||
/**
|
||||
* Create a stream-safe elFinder connector instance.
|
||||
*
|
||||
* @param elFinder $elfinder Configured elFinder instance.
|
||||
* @return elFinderConnector|class_fma_elfinder_connector
|
||||
*/
|
||||
function fma_create_elfinder_connector($elfinder)
|
||||
{
|
||||
if (!class_exists('elFinderConnector')) {
|
||||
$autoload = defined('FMAFILEPATH')
|
||||
? FMAFILEPATH . 'application/library/php/autoload.php'
|
||||
: WP_PLUGIN_DIR . '/file-manager-advanced/application/library/php/autoload.php';
|
||||
if (file_exists($autoload)) {
|
||||
require_once $autoload;
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('class_fma_elfinder_connector')) {
|
||||
$connector_file = defined('FMAFILEPATH')
|
||||
? FMAFILEPATH . 'application/class_fma_elfinder_connector.php'
|
||||
: WP_PLUGIN_DIR . '/file-manager-advanced/application/class_fma_elfinder_connector.php';
|
||||
if (file_exists($connector_file) && class_exists('elFinderConnector')) {
|
||||
require_once $connector_file;
|
||||
}
|
||||
}
|
||||
|
||||
if (class_exists('class_fma_elfinder_connector')) {
|
||||
return new class_fma_elfinder_connector($elfinder);
|
||||
}
|
||||
|
||||
return new elFinderConnector($elfinder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
*~
|
||||
._*
|
||||
_*
|
||||
.DS_Store
|
||||
php-old
|
||||
extensions
|
||||
build
|
||||
files2
|
||||
elFinderVolumeSVN.class.php
|
||||
connector-svn.php
|
||||
node_modules
|
||||
connector.php
|
||||
@@ -0,0 +1,525 @@
|
||||
/*
|
||||
* This is build file for elFinder 2.x
|
||||
* Build tool: https://github.com/mde/jake
|
||||
* JS compressor: https://github.com/mishoo/UglifyJS/
|
||||
* CSS optimizer: https://github.com/css/csso
|
||||
*/
|
||||
|
||||
// if Jake fails to detect need libraries try running before: export NODE_PATH=`npm root`
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
util = require('util'),
|
||||
ugjs = require('uglify-js'),
|
||||
csso = require('csso');
|
||||
|
||||
var dirmode = 0755,
|
||||
src = __dirname,
|
||||
version = null,
|
||||
files = {
|
||||
'elfinder.full.js':
|
||||
[
|
||||
path.join(src, 'js', 'elFinder.js'),
|
||||
path.join(src, 'js', 'elFinder.version.js'),
|
||||
path.join(src, 'js', 'jquery.elfinder.js'),
|
||||
path.join(src, 'js', 'elFinder.mimetypes.js'),
|
||||
path.join(src, 'js', 'elFinder.options.js'),
|
||||
path.join(src, 'js', 'elFinder.options.netmount.js'),
|
||||
path.join(src, 'js', 'elFinder.history.js'),
|
||||
path.join(src, 'js', 'elFinder.command.js'),
|
||||
path.join(src, 'js', 'elFinder.resources.js'),
|
||||
path.join(src, 'js', 'jquery.dialogelfinder.js'),
|
||||
path.join(src, 'js', 'i18n', 'elfinder.en.js')
|
||||
]
|
||||
.concat(grep(path.join(src, 'js', 'ui'), '\\.js$'))
|
||||
.concat(grep(path.join(src, 'js', 'commands'), '\\.js$')),
|
||||
|
||||
'elfinder-minimal.full.js':
|
||||
[
|
||||
path.join(src, 'js', 'elFinder.js'),
|
||||
path.join(src, 'js', 'elFinder.version.js'),
|
||||
path.join(src, 'js', 'jquery.elfinder.js'),
|
||||
//path.join(src, 'js', 'elFinder.mimetypes.js'),
|
||||
path.join(src, 'js', 'elFinder.options.js'),
|
||||
//path.join(src, 'js', 'elFinder.options.netmount.js'),
|
||||
path.join(src, 'js', 'elFinder.history.js'),
|
||||
path.join(src, 'js', 'elFinder.command.js'),
|
||||
path.join(src, 'js', 'elFinder.resources.js'),
|
||||
path.join(src, 'js', 'jquery.dialogelfinder.js'),
|
||||
path.join(src, 'js', 'i18n', 'elfinder.en.js')
|
||||
]
|
||||
.concat(grep(path.join(src, 'js', 'ui'), '(button|contextmenu|cwd|dialog|navbar|navdock|overlay|panel|path|searchbutton|sortbutton|stat|toast|toolbar|tree|uploadbutton|viewbutton|workzone)\\.js$'))
|
||||
.concat(grep(path.join(src, 'js', 'commands'), '(colwidth|copy|cut|duplicate|getfile|help|open|mkdir|paste|restore|rm|search|sort|upload|view)\\.js$')),
|
||||
|
||||
'elfinder.full.css': grep(path.join(src, 'css'), '\\.css$', 'elfinder|theme'),
|
||||
|
||||
'images': grep(path.join(src, 'img'), '\\.png|\\.gif|\\.svg'),
|
||||
|
||||
'sounds': grep(path.join(src, 'sounds'), '\\.wav'),
|
||||
|
||||
'i18n': grep(path.join(src, 'js', 'i18n'), '\\.js', 'elfinder.en.js')
|
||||
.concat(grep(path.join(src, 'js', 'i18n', 'help'), '\\.js')),
|
||||
|
||||
'php':
|
||||
[
|
||||
path.join(src, 'php', 'autoload.php'),
|
||||
path.join(src, 'php', 'connector.minimal.php-dist'),
|
||||
path.join(src, 'php', 'connector.maximal.php-dist'),
|
||||
path.join(src, 'php', 'mime.types'),
|
||||
path.join(src, 'php', 'MySQLStorage.sql'),
|
||||
path.join(src, 'php', 'elFinderPlugin.php'),
|
||||
path.join(src, 'php', 'elFinderSession.php'),
|
||||
path.join(src, 'php', 'elFinderSessionInterface.php'),
|
||||
path.join(src, 'php', '.tmp', '.htaccess'),
|
||||
path.join(src, 'php', 'editors', 'editor.php')
|
||||
]
|
||||
.concat(grep(path.join(src, 'php'), '\\.class\\.php$'))
|
||||
.concat(grep(path.join(src, 'php'), 'Netmount\\.php$'))
|
||||
.concat(grep(path.join(src, 'php', 'libs'), '\\.php$'))
|
||||
.concat(grep(path.join(src, 'php', 'resources'), '.+\..+$')),
|
||||
'misc':
|
||||
[
|
||||
path.join(src, 'js', 'proxy', 'elFinderSupportVer1.js'),
|
||||
path.join(src, 'Changelog'),
|
||||
path.join(src, 'LICENSE.md'),
|
||||
path.join(src, 'README.md'),
|
||||
path.join(src, 'composer.json'),
|
||||
path.join(src, 'elfinder.html'),
|
||||
path.join(src, 'elfinder.legacy.html'),
|
||||
path.join(src, 'main.default.js')
|
||||
]
|
||||
.concat(grep(path.join(src, 'js', 'extras'), '\\.js$'))
|
||||
.concat(grep(path.join(src, 'js', 'worker'), '\\.js$')),
|
||||
'misc-minimal' :
|
||||
[
|
||||
path.join(src, 'js', 'proxy', 'elFinderSupportVer1.js'),
|
||||
path.join(src, 'Changelog'),
|
||||
path.join(src, 'LICENSE.md'),
|
||||
path.join(src, 'README.md'),
|
||||
path.join(src, 'composer.json'),
|
||||
path.join(src, 'elfinder-minimal.html'),
|
||||
path.join(src, 'main-minimal.default.js')
|
||||
]
|
||||
};
|
||||
|
||||
// editors files
|
||||
var editors = [];
|
||||
try {
|
||||
editors = fs.readdirSync(path.join(src, 'php', 'editors')).map(function(n) {
|
||||
return fs.statSync(path.join(src, 'php', 'editors', n)).isFile()? null : n;
|
||||
});
|
||||
} catch (err) { }
|
||||
if (editors.length) {
|
||||
for (var i in editors) {
|
||||
if (editors[i] !== null) {
|
||||
files.php = files.php.concat(grep(path.join(src, 'php', 'editors', editors[i]), '.+'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// plugins files
|
||||
var plugins = [];
|
||||
try {
|
||||
plugins = fs.readdirSync(path.join(src, 'php', 'plugins')).map(function(n) {
|
||||
return fs.statSync(path.join(src, 'php', 'plugins', n)).isFile()? null : n;
|
||||
});
|
||||
} catch (err) { }
|
||||
if (plugins.length) {
|
||||
for (var i in plugins) {
|
||||
if (plugins[i] !== null) {
|
||||
files.php = files.php.concat(grep(path.join(src, 'php', 'plugins', plugins[i]), '.+'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// custom functions
|
||||
function grep(prefix, mask, exculde) {
|
||||
var m = new RegExp(mask);
|
||||
var e = new RegExp(exculde);
|
||||
var o = [];
|
||||
var input = [];
|
||||
try {
|
||||
input = fs.readdirSync(prefix);
|
||||
} catch (err) { }
|
||||
|
||||
for (i in input) {
|
||||
if ((typeof exculde !== 'undefined') && (input[i].match(e))) {
|
||||
//console.log('skip ' + input[i]);
|
||||
continue;
|
||||
}
|
||||
if (input[i].match(m)) {
|
||||
o.push(path.join(prefix, input[i]));
|
||||
}
|
||||
}
|
||||
return o.sort();
|
||||
}
|
||||
|
||||
function copyFile(from, to, overwrite) {
|
||||
if (!overwrite && fs.existsSync(to)) {
|
||||
return false;
|
||||
}
|
||||
console.log('\t' + from);
|
||||
var srcs = fs.createReadStream(from);
|
||||
var dsts = fs.createWriteStream(to);
|
||||
return srcs.pipe(dsts);
|
||||
}
|
||||
|
||||
function getVersion() {
|
||||
var ver = fs.readFileSync(path.join(src, 'js', 'elFinder.version.js')).toString();
|
||||
ver = ver.match(/elFinder.prototype.version = '(.+)';/);
|
||||
return ver[1];
|
||||
}
|
||||
|
||||
function buildComment() {
|
||||
var d = new Date();
|
||||
var buildDate = d.getFullYear() + '-' +
|
||||
(d.getMonth() >= 9 ? '' : '0') + (d.getMonth() + 1) + '-' +
|
||||
(d.getDate() >= 10 ? '' : '0') + d.getDate();
|
||||
var comment =
|
||||
'/*!\n' +
|
||||
' * elFinder - file manager for web\n' +
|
||||
' * Version ' + getVersion() + ' (' + buildDate + ')\n' +
|
||||
' * http://elfinder.org\n' +
|
||||
' * \n' +
|
||||
' * Copyright 2009-' + d.getFullYear() + ', Studio 42\n' +
|
||||
' * Licensed under a 3-clauses BSD license\n' +
|
||||
' */\n';
|
||||
return comment;
|
||||
}
|
||||
|
||||
// tasks
|
||||
desc('Help');
|
||||
task('default', function(){
|
||||
console.log(
|
||||
"This is elFinder build script, run `jake --tasks` for more info, for a default build run:\n" +
|
||||
" jake -C ./build elfinder"
|
||||
);
|
||||
});
|
||||
|
||||
desc('pre build task');
|
||||
task('prebuild', function(){
|
||||
console.log('build dir: ' + path.resolve());
|
||||
console.log('src dir: ' + src);
|
||||
var dir = ['css', 'js', 'img', 'sounds',
|
||||
path.join('js', 'i18n'), path.join('js', 'i18n', 'help'), path.join('js', 'extras'), path.join('js', 'worker'), path.join('js', 'proxy'), path.join('js', 'worker'),
|
||||
'php',
|
||||
path.join('php', '.tmp'), path.join('php', 'libs'), path.join('php', 'resources'),
|
||||
'files', path.join('files', '.trash')],
|
||||
i;
|
||||
if (editors.length) {
|
||||
dir.push(path.join('php', 'editors'));
|
||||
for (i in editors) {
|
||||
(editors[i] !== null) && dir.push(path.join('php', 'editors', editors[i]));
|
||||
}
|
||||
}
|
||||
if (plugins.length) {
|
||||
dir.push(path.join('php', 'plugins'));
|
||||
for (i in plugins) {
|
||||
(plugins[i] !== null) && dir.push(path.join('php', 'plugins', plugins[i]));
|
||||
}
|
||||
}
|
||||
for (var d in dir) {
|
||||
var bd = dir[d];
|
||||
if (!fs.existsSync(bd)) {
|
||||
console.log('mkdir ' + bd);
|
||||
fs.mkdirSync(bd, dirmode);
|
||||
}
|
||||
}
|
||||
//jake.Task['elfinder'].invoke();
|
||||
});
|
||||
|
||||
desc('build elFinder');
|
||||
task({'elfinder': ['clean', 'prebuild', 'css/elfinder.min.css', 'js/elfinder.min.js', 'misc', 'js/extras', 'js/worker']}, function(){
|
||||
console.log('elFinder build done');
|
||||
});
|
||||
|
||||
desc('minimal build elFinder');
|
||||
task({'elfinder-minimal': ['clean', 'prebuild', 'css/elfinder.min.css', 'js/elfinder-minimal.min.js', 'misc-minimal']}, function(){
|
||||
console.log('elFinder build done');
|
||||
});
|
||||
|
||||
// CSS
|
||||
desc('concat elfinder.full.css');
|
||||
file({'css/elfinder.full.css': files['elfinder.full.css']}, function(){
|
||||
console.log('concat ' + this.name);
|
||||
var data = '';
|
||||
for (var f in this.prereqs) {
|
||||
file = this.prereqs[f];
|
||||
console.log('\t' + file);
|
||||
data += '\n/* File: ' + file.replace(src, '') + ' */\n';
|
||||
data += fs.readFileSync(file);
|
||||
}
|
||||
fs.writeFileSync(this.name, buildComment() + data);
|
||||
});
|
||||
|
||||
desc('optimize elfinder.min.css');
|
||||
file({'css/elfinder.min.css': ['css/elfinder.full.css']}, function () {
|
||||
console.log('optimize elfinder.min.css');
|
||||
var cssOptimized = csso.minify(fs.readFileSync('css/elfinder.full.css').toString());
|
||||
fs.writeFileSync(this.name, cssOptimized.css || cssOptimized);
|
||||
});
|
||||
|
||||
// JS
|
||||
desc('concat elfinder.full.js');
|
||||
file({'js/elfinder.full.js': files['elfinder.full.js']}, function(){
|
||||
console.log('concat elfinder.full.js');
|
||||
var strict = new RegExp('"use strict"\;?\n?');
|
||||
var elf = files['elfinder.full.js'];
|
||||
var data = '';
|
||||
for (var f in elf) {
|
||||
file = elf[f];
|
||||
console.log('\t' + file);
|
||||
data += '\n\n/*\n * File: ' + file.replace(src, '') + '\n */\n\n';
|
||||
data += fs.readFileSync(file);
|
||||
data = data.replace(strict, '');
|
||||
}
|
||||
data = "(function(root, factory) {\n" +
|
||||
" if (typeof define === 'function' && define.amd) {\n" +
|
||||
" // AMD\n" +
|
||||
" define(['jquery','jquery-ui'], factory);\n" +
|
||||
" } else if (typeof exports !== 'undefined') {\n" +
|
||||
" // CommonJS\n" +
|
||||
" var $, ui;\n" +
|
||||
" try {\n" +
|
||||
" $ = require('jquery');\n" +
|
||||
" ui = require('jquery-ui');\n" +
|
||||
" } catch (e) {}\n" +
|
||||
" module.exports = factory($, ui);\n" +
|
||||
" } else {\n" +
|
||||
" // Browser globals (Note: root is window)\n" +
|
||||
" factory(root.jQuery, root.jQuery.ui, true);\n" +
|
||||
" }\n" +
|
||||
"}(this, function($, _ui, toGlobal) {\n" +
|
||||
"toGlobal = toGlobal || false;\n" + data + '\nreturn elFinder;\n}));'; // add UMD closure
|
||||
fs.writeFileSync(this.name, buildComment() + data);
|
||||
});
|
||||
|
||||
desc('concat elfinder-minimal.full.js');
|
||||
file({'js/elfinder-minimal.full.js': files['elfinder-minimal.full.js']}, function(){
|
||||
console.log('concat elfinder-minimal.full.js');
|
||||
var strict = new RegExp('"use strict"\;?\n?');
|
||||
var elf = files['elfinder-minimal.full.js'];
|
||||
var data = '';
|
||||
for (var f in elf) {
|
||||
file = elf[f];
|
||||
console.log('\t' + file);
|
||||
data += '\n\n/*\n * File: ' + file.replace(src, '') + '\n */\n\n';
|
||||
data += fs.readFileSync(file);
|
||||
data = data.replace(strict, '');
|
||||
}
|
||||
data = "(function(root, factory) {\n" +
|
||||
" if (typeof define === 'function' && define.amd) {\n" +
|
||||
" // AMD\n" +
|
||||
" define(['jquery','jquery-ui'], factory);\n" +
|
||||
" } else if (typeof exports !== 'undefined') {\n" +
|
||||
" // CommonJS\n" +
|
||||
" var $, ui;\n" +
|
||||
" try {\n" +
|
||||
" $ = require('jquery');\n" +
|
||||
" ui = require('jquery-ui');\n" +
|
||||
" } catch (e) {}\n" +
|
||||
" module.exports = factory($, ui);\n" +
|
||||
" } else {\n" +
|
||||
" // Browser globals (Note: root is window)\n" +
|
||||
" factory(root.jQuery, root.jQuery.ui, true);\n" +
|
||||
" }\n" +
|
||||
"}(this, function($, _ui, toGlobal) {\n" +
|
||||
"toGlobal = toGlobal || false;\n" + data + '\nreturn elFinder;\n}));'; // add UMD closure
|
||||
fs.writeFileSync(this.name, buildComment() + data);
|
||||
});
|
||||
|
||||
desc('uglify elfinder.min.js');
|
||||
file({'js/elfinder.min.js': ['js/elfinder.full.js']}, function () {
|
||||
console.log('uglify elfinder.min.js');
|
||||
var result;
|
||||
if (typeof ugjs.minify == 'undefined') {
|
||||
var ugp = ugjs.parser;
|
||||
var ugu = ugjs.uglify;
|
||||
var ast = ugp.parse(fs.readFileSync('js/elfinder.full.js').toString()); // parse code and get the initial AST
|
||||
ast = ugu.ast_mangle(ast); // get a new AST with mangled names
|
||||
ast = ugu.ast_squeeze(ast); // get an AST with compression optimizations
|
||||
result = ugu.split_lines(ugu.gen_code(ast), 1024 * 8); // insert new line every 8 kb
|
||||
} else {
|
||||
result = ugjs.minify('js/elfinder.full.js').code;
|
||||
}
|
||||
fs.writeFileSync(this.name, buildComment() + result);
|
||||
});
|
||||
|
||||
desc('uglify elfinder-minimal.min.js');
|
||||
file({'js/elfinder-minimal.min.js': ['js/elfinder-minimal.full.js']}, function () {
|
||||
console.log('uglify elfinder-minimal.min.js');
|
||||
var result;
|
||||
if (typeof ugjs.minify == 'undefined') {
|
||||
var ugp = ugjs.parser;
|
||||
var ugu = ugjs.uglify;
|
||||
var ast = ugp.parse(fs.readFileSync('js/elfinder-minimal.full.js').toString()); // parse code and get the initial AST
|
||||
ast = ugu.ast_mangle(ast); // get a new AST with mangled names
|
||||
ast = ugu.ast_squeeze(ast); // get an AST with compression optimizations
|
||||
result = ugu.split_lines(ugu.gen_code(ast), 1024 * 8); // insert new line every 8 kb
|
||||
} else {
|
||||
result = ugjs.minify('js/elfinder-minimal.full.js').code;
|
||||
}
|
||||
fs.writeFileSync(this.name, buildComment() + result);
|
||||
});
|
||||
|
||||
// IMG + SOUNDS + I18N + PHP
|
||||
desc('copy misc files');
|
||||
task('misc', function(){
|
||||
console.log('copy misc files');
|
||||
var cf = files['images']
|
||||
.concat(files['sounds'])
|
||||
.concat(files['i18n'])
|
||||
.concat(path.join(src, 'css', 'theme.css'))
|
||||
.concat(files['php'])
|
||||
.concat(files['misc'])
|
||||
.concat(path.join(src, 'files', '.gitignore'))
|
||||
.concat(path.join(src, 'files', '.trash', '.gitignore'));
|
||||
for (i in cf)
|
||||
{
|
||||
var dst = cf[i].replace(src, '').substr(1);
|
||||
copyFile(cf[i], dst);
|
||||
}
|
||||
// elfinder.html
|
||||
// var hs = path.join(src, 'build', 'elfinder.html');
|
||||
// var hd = path.join('elfinder.html');
|
||||
// copyFile(hs, hd);
|
||||
|
||||
// connector
|
||||
//var cs = path.join(src, 'php', 'connector.minimal.php-dist');
|
||||
//var cd = path.join('php', 'connector.php-dist');
|
||||
//copyFile(cs, cd);
|
||||
});
|
||||
|
||||
// IMG + SOUNDS + I18N + PHP
|
||||
desc('copy misc files');
|
||||
task('misc-minimal', function(){
|
||||
console.log('copy misc files');
|
||||
var cf = files['images']
|
||||
.concat(files['sounds'])
|
||||
.concat(files['i18n'])
|
||||
.concat(path.join(src, 'css', 'theme.css'))
|
||||
.concat(files['php'])
|
||||
.concat(files['misc-minimal'])
|
||||
.concat(path.join(src, 'files', '.gitignore'))
|
||||
.concat(path.join(src, 'files', '.trash', '.gitignore'));
|
||||
for (i in cf)
|
||||
{
|
||||
var dst = cf[i].replace(src, '').substr(1);
|
||||
copyFile(cf[i], dst);
|
||||
}
|
||||
});
|
||||
|
||||
desc('uglify js/extras');
|
||||
task('js/extras', function(){
|
||||
var files = grep(path.join(src, 'js', 'extras'), '\\.js$');
|
||||
var base, name, result;
|
||||
for (var i in files) {
|
||||
name = files[i].replace(/^.+\/([^\/]+)$/, '$1');
|
||||
if (! name.match(/\.min\./)) {
|
||||
base = name.replace(/\.js$/, '');
|
||||
name = 'js/extras/' + name;
|
||||
console.log('uglify ' + name);
|
||||
if (typeof ugjs.minify == 'undefined') {
|
||||
var ugp = ugjs.parser;
|
||||
var ugu = ugjs.uglify;
|
||||
var ast = ugp.parse(fs.readFileSync(files[i]).toString()); // parse code and get the initial AST
|
||||
ast = ugu.ast_mangle(ast); // get a new AST with mangled names
|
||||
ast = ugu.ast_squeeze(ast); // get an AST with compression optimizations
|
||||
result = ugu.split_lines(ugu.gen_code(ast), 1024 * 8); // insert new line every 8 kb
|
||||
} else {
|
||||
result = ugjs.minify(files[i]).code;
|
||||
}
|
||||
fs.writeFileSync('js/extras/' + base + '.min.js', result);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// other
|
||||
desc('clean build dir');
|
||||
task('clean', function(){
|
||||
console.log('cleaning the floor');
|
||||
uf = [path.join('js', 'elfinder.full.js'), path.join('js', 'elfinder.min.js'),
|
||||
path.join('css', 'elfinder.full.css'), path.join('css', 'elfinder.min.css')];
|
||||
// clean images, sounds, js/i18n and php only if we are not in src
|
||||
if (src != path.resolve()) {
|
||||
uf = uf
|
||||
.concat(grep('./'))
|
||||
.concat(grep('css'))
|
||||
.concat(grep('files'))
|
||||
.concat(grep('img'))
|
||||
.concat(grep('js'))
|
||||
.concat(grep('php'))
|
||||
.concat(grep('sounds'));
|
||||
uf = [].concat.apply(uf, grep('files').map(function(d) { return grep(d); }));
|
||||
uf = [].concat.apply(uf, grep('js').map(function(d) { return grep(d); }));
|
||||
uf = [].concat.apply(uf, grep(path.join('js', 'i18n')).map(function(d) { return grep(d); }));
|
||||
uf = [].concat.apply(uf, grep('php').map(function(d) { return grep(d); }));
|
||||
uf = [].concat.apply(uf, grep(path.join('php', 'editors')).map(function(d) { return grep(d); }));
|
||||
uf = [].concat.apply(uf, grep(path.join('php', 'plugins')).map(function(d) { return grep(d); }));
|
||||
}
|
||||
for (var f in uf) {
|
||||
var file = uf[f];
|
||||
if (fs.existsSync(file) && fs.statSync(file).isFile()) {
|
||||
console.log('\tunlink ' + file);
|
||||
fs.unlinkSync(file);
|
||||
}
|
||||
}
|
||||
// if (path.join(src, 'build') != path.resolve()) {
|
||||
// fs.unlinkSync('elfinder.html');
|
||||
// }
|
||||
if (src != path.resolve()) {
|
||||
var ud = [
|
||||
'css', 'img', 'sounds', path.join('files', '.trash'), 'files',
|
||||
path.join('js', 'proxy'), path.join('js', 'i18n', 'help'), path.join('js', 'i18n'), path.join('js', 'extras'), path.join('js', 'worker'), 'js',
|
||||
path.join('php', '.tmp'), path.join('php', 'libs'), path.join('php', 'resources')]
|
||||
.concat(grep(path.join('php', 'editors')))
|
||||
.concat(grep(path.join('php', 'plugins')))
|
||||
.concat([path.join('php', 'editors'), path.join('php', 'plugins'), 'php']);
|
||||
for (var d in ud) {
|
||||
var dir = ud[d];
|
||||
if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
|
||||
console.log('\trmdir ' + dir);
|
||||
fs.rmdirSync(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
desc('get current build version from git');
|
||||
task('version', function(){
|
||||
version = getVersion();
|
||||
console.log('Version: ' + version);
|
||||
complete();
|
||||
}, {async: true});
|
||||
|
||||
desc('create package task');
|
||||
task('prepack', function(){
|
||||
new jake.PackageTask('elfinder', version, function(){
|
||||
var fls = (files['php'].concat(files['images']).concat(files['sounds']).concat(files['i18n']).concat(files['misc'])).map(function(i){
|
||||
return i.substr(src.length + 1);
|
||||
});
|
||||
fls.push(path.join('css', 'elfinder.min.css'));
|
||||
fls.push(path.join('css', 'theme.css'));
|
||||
fls.push(path.join('js', 'elfinder.min.js'));
|
||||
fls.push('files');
|
||||
console.log('Including next files into release:');
|
||||
console.log(fls);
|
||||
this.packageFiles.items = fls;
|
||||
this.needTarGz = true;
|
||||
this.needZip = true;
|
||||
});
|
||||
});
|
||||
|
||||
desc('pack release');
|
||||
task({'release': ['version']}, function(){
|
||||
var prePack = jake.Task['prepack'];
|
||||
prePack.addListener('complete', function() {
|
||||
var pack = jake.Task['package'];
|
||||
pack.addListener('complete', function() {
|
||||
console.log('Created package for elFinder ' + version);
|
||||
complete();
|
||||
});
|
||||
pack.invoke();
|
||||
});
|
||||
prePack.invoke();
|
||||
}, {async: true});
|
||||
@@ -0,0 +1,15 @@
|
||||
elFinder is issued under a 3-clauses BSD license.
|
||||
|
||||
Copyright (c) 2009-2024, Studio 42
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the Studio 42 Ltd. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL "STUDIO 42" OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,217 @@
|
||||
elFinder
|
||||
========
|
||||
|
||||
**WARNING: IF YOU HAVE OLDER (IN PARTICULAR 2.1.66 OR EARLIER) VERSIONS OF ELFINDER ON PUBLIC SERVERS, IT MAY CAUSE SERIOUS DAMAGE TO YOUR SERVER AND VISITED USER. YOU SHOULD UPDATE TO THE LATEST VERSION OR REMOVE IT FROM THE SERVER.**
|
||||
|
||||
[](https://studio-42.github.io/elFinder/)
|
||||
|
||||
elFinder is an open-source file manager for web, written in JavaScript using
|
||||
jQuery UI. Creation is inspired by simplicity and convenience of Finder program
|
||||
used in Mac OS X operating system.
|
||||
|
||||
[](https://github.com/Studio-42/elFinder/releases/latest)
|
||||
[](https://choosealicense.com/licenses/bsd-3-clause/)
|
||||
[](https://packagist.org/packages/studio-42/elfinder)
|
||||
[](https://packagist.org/packages/studio-42/elfinder)
|
||||
[](https://cdnjs.com/libraries/elfinder)
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FF5FKRSMKYDVA)
|
||||
[](https://studio-42.github.io/elFinder/tools/donate-bitcoin/)
|
||||
[](https://www.buymeacoffee.com/naopon)
|
||||
|
||||
Contents
|
||||
--------
|
||||
* [Branches](#branches)
|
||||
* [Features](#features)
|
||||
* [Requirements](#requirements)
|
||||
* [Installation](#installation)
|
||||
* [Downloads](#downloads)
|
||||
* [Demo Sites](#demo-sites)
|
||||
* [FAQs](#faqs)
|
||||
* [3rd Party Connectors](#3rd-party-connectors)
|
||||
* [3rd Party Volume Drivers](#3rd-party-volume-drivers)
|
||||
* [3rd Party Themes](#3rd-party-themes)
|
||||
* [Support](#support)
|
||||
* [Authors](#authors)
|
||||
* [License](#license)
|
||||
|
||||
Branches
|
||||
--------
|
||||
- [master](https://github.com/Studio-42/elFinder/tree/master) - Main development branch
|
||||
- [2.1-src](https://github.com/Studio-42/elFinder/tree/2.1-src) - 2.1 development branch, auto build to 2.1 on commit
|
||||
- [2.1](https://github.com/Studio-42/elFinder/tree/2.1) - 2.1 nightly build branch
|
||||
|
||||
Features
|
||||
--------
|
||||
* Usability like the MacOS Finder or Windows Explorer
|
||||
* Mobile friendly view for touch devices
|
||||
* All operations with files and folders on a remote server (copy, move,
|
||||
upload, create folder/file, rename, etc.)
|
||||
* High performance server backend and light client UI
|
||||
* Multi-root support
|
||||
* Local file system, MySQL, FTP, SFTP, Box, Dropbox, GoogleDrive and OneDrive volume storage drivers
|
||||
* Support AWS S3, Azure, Digital Ocean Spaces and more with [League\Flysystem](https://github.com/barryvdh/elfinder-flysystem-driver) Flysystem driver
|
||||
* Cloud storage (Box, Dropbox, GoogleDrive and OneDrive) drivers
|
||||
* Background file/folder upload with Drag & Drop HTML5 support
|
||||
* Chunked file upload for large file
|
||||
* Upload directly to the folder
|
||||
* Upload form URL (or list)
|
||||
* List and Icons view
|
||||
* Keyboard shortcuts
|
||||
* Standard methods of file/group selection using mouse or keyboard
|
||||
* Move/Copy files with Drag & Drop
|
||||
* Drag & Drop to outside by starting drag with alt/option key press
|
||||
* Archives create/extract (zip, rar, 7z, tar, gzip, bzip2)
|
||||
* Rich context menu and toolbar
|
||||
* Quicklook, preview for common file types
|
||||
* Edit text files and images
|
||||
* "Places" for your favorites
|
||||
* Calculate directory sizes
|
||||
* Thumbnails for image, movie files
|
||||
* Easy to integrate with web editors (elRTE, CKEditor, TinyMCE)
|
||||
* Flexible configuration of access rights, upload file types, user interface
|
||||
and other
|
||||
* Extensibility by event handling of backend and client side
|
||||
* Simple client-server API based on JSON
|
||||
* Supports custom information in info dialog
|
||||
* Configuable columns of list view
|
||||
* Supports custom CSS class function for the custom folder icon
|
||||
* Connector plugin
|
||||
* [AutoRotate](https://github.com/Studio-42/elFinder/blob/2.1-src/php/plugins/AutoRotate/plugin.php) : Auto rotation on file upload of JPEG file by EXIF Orientation.
|
||||
* [AutoResize](https://github.com/Studio-42/elFinder/blob/2.1-src/php/plugins/AutoResize/plugin.php) : Auto resize on file upload.
|
||||
* [Normalizer](https://github.com/Studio-42/elFinder/blob/2.1-src/php/plugins/Normalizer/plugin.php) : UTF-8 Normalizer of file-name and file-path etc.
|
||||
* [Sanitizer](https://github.com/Studio-42/elFinder/blob/2.1-src/php/plugins/Sanitizer/plugin.php) : Sanitizer of file-name and file-path etc.
|
||||
* [Watermark](https://github.com/Studio-42/elFinder/blob/2.1-src/php/plugins/Watermark/plugin.php) : Print watermark on file upload.
|
||||
* For more details, see the [Changelog](https://github.com/Studio-42/elFinder/blob/master/Changelog)
|
||||
|
||||
Requirements
|
||||
------------
|
||||
### jQuery / jQuery UI
|
||||
* jQuery 1.8.0+
|
||||
* jQuery UI 1.9.0+
|
||||
* Required: draggable, droppable, resizable, selectable, button and slider
|
||||
* Recommend: sorter (To make sortable the List column and the Places)
|
||||
|
||||
**However, we recommend newest version.**
|
||||
|
||||
### Client
|
||||
* Modern browsers both of desktop or mobile. elFinder was tested in newest Chrome, Edge, Firefox, IE and Opera
|
||||
- **Caution**: Web App mode ("apple-mobile-web-app-capable" meta tag) on iOS is not work perfectly in elFinder
|
||||
|
||||
### Server
|
||||
* Any web server
|
||||
* PHP 5.2+ (Recommend PHP 5.4 or higher) And for thumbnails - GD / Imagick module / convert(imagemagick) require
|
||||
* Recommend PHP 7.1 or higher to supports non-ASCII character of file path/name on the Windows server
|
||||
|
||||
Installation
|
||||
------------
|
||||
### Builds (compressed)
|
||||
1. Download and unzip one of the [builds](#downloads) below to your PHP server
|
||||
2. Rename `/php/connector.minimal.php-dist` to `/php/connector.minimal.php`
|
||||
3. Load `/elfinder.html` in your browser to run elFinder
|
||||
|
||||
### Source (uncompressed)
|
||||
1. Clone this repository to your PHP server
|
||||
|
||||
```
|
||||
$ git clone https://github.com/Studio-42/elFinder.git
|
||||
```
|
||||
|
||||
2. Rename `/php/connector.minimal.php-dist` to `/php/connector.minimal.php`
|
||||
3. Load `/elfinder.src.html` in your browser to run elFinder
|
||||
|
||||
### Installer
|
||||
- [Setup elFinder 2.1.x nightly with Composer](https://github.com/Studio-42/elFinder/tree/gh-pages/tools/installer/setup_with_composer)
|
||||
|
||||
Downloads
|
||||
------------
|
||||
**Stable releases** ([Changelog](https://github.com/Studio-42/elFinder/blob/master/Changelog))
|
||||
+ [elFinder 2.1.67](https://github.com/Studio-42/elFinder/archive/2.1.67.zip)
|
||||
+ [elFinder 2.0.9](https://github.com/Studio-42/elFinder/archive/2.0.9.zip) (deprecated)
|
||||
|
||||
**Nightly builds**
|
||||
+ [elFinder 2.1.x (Nightly)](https://github.com/Studio-42/elFinder/archive/2.1.zip)
|
||||
|
||||
Demo sites
|
||||
------------
|
||||
**2.1.x Nightly**
|
||||
+ https://studio-42.github.io/elFinder/ (with CORS)
|
||||
|
||||
FAQs
|
||||
------------
|
||||
|
||||
### Should I use elFinder builds (compressed) or source (uncompressed)?
|
||||
|
||||
For debugging and development, use the [source](#source-uncompressed). For production, use [builds](#builds-compressed).
|
||||
|
||||
### How do I integrate elFinder with CKEditor/TinyMCE/elRTE/etc...?
|
||||
Check out the [wiki](https://github.com/studio-42/elFinder/wiki#howtos) for individual instructions.
|
||||
|
||||
### The procedure of language files created or modified?
|
||||
|
||||
You can create or modify the language file to use translation tool. Please refer to the pull request the results to the respective branch.
|
||||
* [2.1 branch translation tool](http://studio-42.github.io/elFinder/tools/langman/#2.1)
|
||||
|
||||
|
||||
3rd party connectors
|
||||
--------------------
|
||||
* [ASP.NET](https://github.com/leniel/elFinder.Net) / [ASP.NET Core](https://github.com/gordon-matt/elFinder.NetCore) / [.NET Standard](https://github.com/mguinness/elFinder.AspNet)
|
||||
* [Java Servlet](https://github.com/trustsystems/elfinder-java-connector)
|
||||
* [JavaScript/Efw](https://github.com/efwGrp/efw3.X/blob/master/help/tag.elfinder.md)
|
||||
* [Nodejs](https://github.com/dekyfin/elfinder-node)
|
||||
* [Python](https://github.com/Studio-42/elfinder-python)
|
||||
* [Ruby/Rails](https://github.com/phallstrom/el_finder)
|
||||
|
||||
3rd party Volume Drivers
|
||||
--------------------
|
||||
* [League\Flysystem (PHP)](https://github.com/barryvdh/elfinder-flysystem-driver) (for elFinder 2.1+) driver for the [Flysystem](https://github.com/thephpleague/flysystem)
|
||||
|
||||
3rd party Themes
|
||||
--------------------
|
||||
Hint: [How to load CSS with RequireJS?](https://github.com/Studio-42/elFinder/wiki/How-to-load-CSS-with-RequireJS%3F)
|
||||
|
||||
* [lokothodida/elfinder-theme-moono](https://github.com/lokothodida/elfinder-theme-moono)
|
||||
* [lokothodida/elfinder-theme-windows-10](https://github.com/lokothodida/elfinder-theme-windows-10)
|
||||
* [RobiNN1/elFinder-Material-Theme](https://github.com/RobiNN1/elFinder-Material-Theme)
|
||||
* [StudioJunkyard/elfinder-boostrap-theme](https://github.com/StudioJunkyard/LibreICONS/tree/master/themes/elFinder)
|
||||
|
||||
3rd party Integrations
|
||||
--------------------
|
||||
* [Django](https://github.com/mikery/django-elfinder)
|
||||
* [Drupal](https://gitlab.com/667bdrm/elfinder)
|
||||
* [Laravel](https://github.com/barryvdh/laravel-elfinder)
|
||||
* [Roundcube](https://github.com/Offerel/roundcube_elfinder)
|
||||
* [Symfony](https://github.com/helios-ag/FMElfinderBundle)
|
||||
* [Tiki Wiki](https://doc.tiki.org/elFinder)
|
||||
* [WordPress](https://wordpress.org/plugins/file-manager/)
|
||||
* [XOOPS](https://github.com/nao-pon/xelfinder)
|
||||
* [XOOPSCube](https://github.com/xoopscube/xelfinder) GUI-based control panel: FTP, cloud storage and editors
|
||||
* [Yii](http://www.yiiframework.com/extension/elfinder/)
|
||||
* [Zenphoto](http://www.zenphoto.org/news/elfinder/)
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
* [Homepage](http://elfinder.org)
|
||||
* [Wiki](https://github.com/Studio-42/elFinder/wiki)
|
||||
* [Issues](https://github.com/Studio-42/elFinder/issues)
|
||||
* <dev@std42.ru>
|
||||
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
* Current main developer: Naoki Sawada <hypweb+elfinder@gmail.com> [](https://www.buymeacoffee.com/naopon)
|
||||
* Chief developer: Dmitry "dio" Levashov <dio@std42.ru>
|
||||
* Maintainer: Troex Nevelin <troex@fury.scancode.ru>
|
||||
* Developers: Alexey Sukhotin, Naoki Sawada <hypweb+elfinder@gmail.com>
|
||||
* Icons: PixelMixer, [Yusuke Kamiyamane](http://p.yusukekamiyamane.com), [Icons8](https://icons8.com)
|
||||
|
||||
We hope our tools will be helpful for you.
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
elFinder is issued under a 3-clauses BSD license.
|
||||
|
||||
* [License terms](https://github.com/Studio-42/elFinder/blob/master/LICENSE.md)
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "elfinder",
|
||||
"authors": [
|
||||
"Dmitry \"dio\" Levashov <dio@std42.ru>",
|
||||
"Troex Nevelin <troex@fury.scancode.ru>",
|
||||
"Alexey Sukhotin <strogg@yandex.ru>",
|
||||
"Naoki Sawada <hypweb@gmail.com>"
|
||||
],
|
||||
"description": "Open-source file manager for web, written in JavaScript using jQuery and jQuery UI.",
|
||||
"dependencies": {
|
||||
"jquery": "1.8.0 - 3",
|
||||
"jquery-ui": "^1.9.x"
|
||||
},
|
||||
"keywords": [
|
||||
"filemanager",
|
||||
"jquery",
|
||||
"jquery-ui",
|
||||
"javascript",
|
||||
"php"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"homepage": "https://github.com/Studio-42/elFinder",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"jquery",
|
||||
"php"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
/* BASICS */
|
||||
|
||||
.CodeMirror {
|
||||
/* Set height, width, borders, and global font properties here */
|
||||
font-family: monospace;
|
||||
height: inherit;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
|
||||
.CodeMirror-lines {
|
||||
padding: 4px 0; /* Vertical padding around content */
|
||||
}
|
||||
.CodeMirror pre {
|
||||
padding: 0 4px; /* Horizontal padding of content */
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||
background-color: white; /* The little square between H and V scrollbars */
|
||||
}
|
||||
|
||||
/* GUTTER */
|
||||
|
||||
.CodeMirror-gutters {
|
||||
border-right: 1px solid #ddd;
|
||||
background-color: #f7f7f7;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.CodeMirror-linenumbers {}
|
||||
.CodeMirror-linenumber {
|
||||
padding: 0 3px 0 5px;
|
||||
min-width: 20px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.CodeMirror-guttermarker { color: black; }
|
||||
.CodeMirror-guttermarker-subtle { color: #999; }
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror-cursor {
|
||||
border-left: 1px solid black;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror div.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.cm-fat-cursor .CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0 !important;
|
||||
background: #7e7;
|
||||
}
|
||||
.cm-fat-cursor div.CodeMirror-cursors {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.cm-animate-fat-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||
-moz-animation: blink 1.06s steps(1) infinite;
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
background-color: #7e7;
|
||||
}
|
||||
@-moz-keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
@-webkit-keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
@keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
.CodeMirror-overwrite .CodeMirror-cursor {}
|
||||
|
||||
.cm-tab { display: inline-block; text-decoration: inherit; }
|
||||
|
||||
.CodeMirror-rulers {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: -50px; bottom: -20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.CodeMirror-ruler {
|
||||
border-left: 1px solid #ccc;
|
||||
top: 0; bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* DEFAULT THEME */
|
||||
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
.cm-strikethrough {text-decoration: line-through;}
|
||||
|
||||
.cm-s-default .cm-keyword {color: #708;}
|
||||
.cm-s-default .cm-atom {color: #219;}
|
||||
.cm-s-default .cm-number {color: #164;}
|
||||
.cm-s-default .cm-def {color: #00f;}
|
||||
.cm-s-default .cm-variable,
|
||||
.cm-s-default .cm-punctuation,
|
||||
.cm-s-default .cm-property,
|
||||
.cm-s-default .cm-operator {}
|
||||
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||
.cm-s-default .cm-variable-3 {color: #085;}
|
||||
.cm-s-default .cm-comment {color: #a50;}
|
||||
.cm-s-default .cm-string {color: #a11;}
|
||||
.cm-s-default .cm-string-2 {color: #f50;}
|
||||
.cm-s-default .cm-meta {color: #555;}
|
||||
.cm-s-default .cm-qualifier {color: #555;}
|
||||
.cm-s-default .cm-builtin {color: #30a;}
|
||||
.cm-s-default .cm-bracket {color: #997;}
|
||||
.cm-s-default .cm-tag {color: #170;}
|
||||
.cm-s-default .cm-attribute {color: #00c;}
|
||||
.cm-s-default .cm-hr {color: #999;}
|
||||
.cm-s-default .cm-link {color: #00c;}
|
||||
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
.CodeMirror-composing { border-bottom: 2px solid; }
|
||||
|
||||
/* Default styles for common addons */
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
|
||||
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||
|
||||
/* STOP */
|
||||
|
||||
/* The rest of this file contains styles related to the mechanics of
|
||||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
overflow: scroll !important; /* Things will break if this is overridden */
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
/* See overflow: hidden in .CodeMirror */
|
||||
margin-bottom: -30px; margin-right: -30px;
|
||||
padding-bottom: 30px;
|
||||
height: 100%;
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
position: relative;
|
||||
}
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
border-right: 30px solid transparent;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
before actual scrolling happens, thus preventing shaking and
|
||||
flickering artifacts. */
|
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
display: none;
|
||||
}
|
||||
.CodeMirror-vscrollbar {
|
||||
right: 0; top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.CodeMirror-hscrollbar {
|
||||
bottom: 0; left: 0;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.CodeMirror-scrollbar-filler {
|
||||
right: 0; bottom: 0;
|
||||
}
|
||||
.CodeMirror-gutter-filler {
|
||||
left: 0; bottom: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute; left: 0; top: 0;
|
||||
min-height: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
.CodeMirror-gutter {
|
||||
white-space: normal;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-bottom: -30px;
|
||||
/* Hack to make IE7 behave */
|
||||
*zoom:1;
|
||||
*display:inline;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
.CodeMirror-gutter-background {
|
||||
position: absolute;
|
||||
top: 0; bottom: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.CodeMirror-lines {
|
||||
cursor: text;
|
||||
min-height: 1px; /* prevents collapsing before first draw */
|
||||
}
|
||||
.CodeMirror pre {
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
|
||||
border-width: 0;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin: 0;
|
||||
white-space: pre;
|
||||
word-wrap: normal;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-font-variant-ligatures: none;
|
||||
font-variant-ligatures: none;
|
||||
}
|
||||
.CodeMirror-wrap pre {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.CodeMirror-linebackground {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-linewidget {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.CodeMirror-widget {}
|
||||
|
||||
.CodeMirror-code {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Force content-box sizing for the elements where we expect it */
|
||||
.CodeMirror-scroll,
|
||||
.CodeMirror-sizer,
|
||||
.CodeMirror-gutter,
|
||||
.CodeMirror-gutters,
|
||||
.CodeMirror-linenumber {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
div.CodeMirror-dragcursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-focused div.CodeMirror-cursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-selected { background: #d9d9d9; }
|
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||
.CodeMirror-crosshair { cursor: crosshair; }
|
||||
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
|
||||
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
|
||||
|
||||
.cm-searching {
|
||||
background: #ffa;
|
||||
background: rgba(255, 255, 0, .4);
|
||||
}
|
||||
|
||||
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
|
||||
.CodeMirror span { *vertical-align: text-bottom; }
|
||||
|
||||
/* Used to force a border model for a node */
|
||||
.cm-force-border { padding-right: .1px; }
|
||||
|
||||
@media print {
|
||||
/* Hide the cursor when printing */
|
||||
.CodeMirror div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* See issue #2901 */
|
||||
.cm-tab-wrap-hack:after { content: ''; }
|
||||
|
||||
/* Help users use markselection to safely style text background */
|
||||
span.CodeMirror-selectedtext { background: none; }
|
||||
@@ -0,0 +1,174 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("apl", function() {
|
||||
var builtInOps = {
|
||||
".": "innerProduct",
|
||||
"\\": "scan",
|
||||
"/": "reduce",
|
||||
"⌿": "reduce1Axis",
|
||||
"⍀": "scan1Axis",
|
||||
"¨": "each",
|
||||
"⍣": "power"
|
||||
};
|
||||
var builtInFuncs = {
|
||||
"+": ["conjugate", "add"],
|
||||
"−": ["negate", "subtract"],
|
||||
"×": ["signOf", "multiply"],
|
||||
"÷": ["reciprocal", "divide"],
|
||||
"⌈": ["ceiling", "greaterOf"],
|
||||
"⌊": ["floor", "lesserOf"],
|
||||
"∣": ["absolute", "residue"],
|
||||
"⍳": ["indexGenerate", "indexOf"],
|
||||
"?": ["roll", "deal"],
|
||||
"⋆": ["exponentiate", "toThePowerOf"],
|
||||
"⍟": ["naturalLog", "logToTheBase"],
|
||||
"○": ["piTimes", "circularFuncs"],
|
||||
"!": ["factorial", "binomial"],
|
||||
"⌹": ["matrixInverse", "matrixDivide"],
|
||||
"<": [null, "lessThan"],
|
||||
"≤": [null, "lessThanOrEqual"],
|
||||
"=": [null, "equals"],
|
||||
">": [null, "greaterThan"],
|
||||
"≥": [null, "greaterThanOrEqual"],
|
||||
"≠": [null, "notEqual"],
|
||||
"≡": ["depth", "match"],
|
||||
"≢": [null, "notMatch"],
|
||||
"∈": ["enlist", "membership"],
|
||||
"⍷": [null, "find"],
|
||||
"∪": ["unique", "union"],
|
||||
"∩": [null, "intersection"],
|
||||
"∼": ["not", "without"],
|
||||
"∨": [null, "or"],
|
||||
"∧": [null, "and"],
|
||||
"⍱": [null, "nor"],
|
||||
"⍲": [null, "nand"],
|
||||
"⍴": ["shapeOf", "reshape"],
|
||||
",": ["ravel", "catenate"],
|
||||
"⍪": [null, "firstAxisCatenate"],
|
||||
"⌽": ["reverse", "rotate"],
|
||||
"⊖": ["axis1Reverse", "axis1Rotate"],
|
||||
"⍉": ["transpose", null],
|
||||
"↑": ["first", "take"],
|
||||
"↓": [null, "drop"],
|
||||
"⊂": ["enclose", "partitionWithAxis"],
|
||||
"⊃": ["diclose", "pick"],
|
||||
"⌷": [null, "index"],
|
||||
"⍋": ["gradeUp", null],
|
||||
"⍒": ["gradeDown", null],
|
||||
"⊤": ["encode", null],
|
||||
"⊥": ["decode", null],
|
||||
"⍕": ["format", "formatByExample"],
|
||||
"⍎": ["execute", null],
|
||||
"⊣": ["stop", "left"],
|
||||
"⊢": ["pass", "right"]
|
||||
};
|
||||
|
||||
var isOperator = /[\.\/⌿⍀¨⍣]/;
|
||||
var isNiladic = /⍬/;
|
||||
var isFunction = /[\+−×÷⌈⌊∣⍳\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/;
|
||||
var isArrow = /←/;
|
||||
var isComment = /[⍝#].*$/;
|
||||
|
||||
var stringEater = function(type) {
|
||||
var prev;
|
||||
prev = false;
|
||||
return function(c) {
|
||||
prev = c;
|
||||
if (c === type) {
|
||||
return prev === "\\";
|
||||
}
|
||||
return true;
|
||||
};
|
||||
};
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
prev: false,
|
||||
func: false,
|
||||
op: false,
|
||||
string: false,
|
||||
escape: false
|
||||
};
|
||||
},
|
||||
token: function(stream, state) {
|
||||
var ch, funcName;
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
ch = stream.next();
|
||||
if (ch === '"' || ch === "'") {
|
||||
stream.eatWhile(stringEater(ch));
|
||||
stream.next();
|
||||
state.prev = true;
|
||||
return "string";
|
||||
}
|
||||
if (/[\[{\(]/.test(ch)) {
|
||||
state.prev = false;
|
||||
return null;
|
||||
}
|
||||
if (/[\]}\)]/.test(ch)) {
|
||||
state.prev = true;
|
||||
return null;
|
||||
}
|
||||
if (isNiladic.test(ch)) {
|
||||
state.prev = false;
|
||||
return "niladic";
|
||||
}
|
||||
if (/[¯\d]/.test(ch)) {
|
||||
if (state.func) {
|
||||
state.func = false;
|
||||
state.prev = false;
|
||||
} else {
|
||||
state.prev = true;
|
||||
}
|
||||
stream.eatWhile(/[\w\.]/);
|
||||
return "number";
|
||||
}
|
||||
if (isOperator.test(ch)) {
|
||||
return "operator apl-" + builtInOps[ch];
|
||||
}
|
||||
if (isArrow.test(ch)) {
|
||||
return "apl-arrow";
|
||||
}
|
||||
if (isFunction.test(ch)) {
|
||||
funcName = "apl-";
|
||||
if (builtInFuncs[ch] != null) {
|
||||
if (state.prev) {
|
||||
funcName += builtInFuncs[ch][1];
|
||||
} else {
|
||||
funcName += builtInFuncs[ch][0];
|
||||
}
|
||||
}
|
||||
state.func = true;
|
||||
state.prev = false;
|
||||
return "function " + funcName;
|
||||
}
|
||||
if (isComment.test(ch)) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
if (ch === "∘" && stream.peek() === ".") {
|
||||
stream.next();
|
||||
return "function jot-dot";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
state.prev = true;
|
||||
return "keyword";
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/apl", "apl");
|
||||
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: APL mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="./apl.js"></script>
|
||||
<style>
|
||||
.CodeMirror { border: 2px inset #dee; }
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">APL</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>APL mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
⍝ Conway's game of life
|
||||
|
||||
⍝ This example was inspired by the impressive demo at
|
||||
⍝ http://www.youtube.com/watch?v=a9xAKttWgP4
|
||||
|
||||
⍝ Create a matrix:
|
||||
⍝ 0 1 1
|
||||
⍝ 1 1 0
|
||||
⍝ 0 1 0
|
||||
creature ← (3 3 ⍴ ⍳ 9) ∈ 1 2 3 4 7 ⍝ Original creature from demo
|
||||
creature ← (3 3 ⍴ ⍳ 9) ∈ 1 3 6 7 8 ⍝ Glider
|
||||
|
||||
⍝ Place the creature on a larger board, near the centre
|
||||
board ← ¯1 ⊖ ¯2 ⌽ 5 7 ↑ creature
|
||||
|
||||
⍝ A function to move from one generation to the next
|
||||
life ← {∨/ 1 ⍵ ∧ 3 4 = ⊂+/ +⌿ 1 0 ¯1 ∘.⊖ 1 0 ¯1 ⌽¨ ⊂⍵}
|
||||
|
||||
⍝ Compute n-th generation and format it as a
|
||||
⍝ character matrix
|
||||
gen ← {' #'[(life ⍣ ⍵) board]}
|
||||
|
||||
⍝ Show first three generations
|
||||
(gen 1) (gen 2) (gen 3)
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/apl"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Simple mode that tries to handle APL as well as it can.</p>
|
||||
<p>It attempts to label functions/operators based upon
|
||||
monadic/dyadic usage (but this is far from fully fleshed out).
|
||||
This means there are meaningful classnames so hover states can
|
||||
have popups etc.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/apl</code> (APL code)</p>
|
||||
</article>
|
||||
@@ -0,0 +1,73 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
function errorIfNotEmpty(stream) {
|
||||
var nonWS = stream.match(/^\s*\S/);
|
||||
stream.skipToEnd();
|
||||
return nonWS ? "error" : null;
|
||||
}
|
||||
|
||||
CodeMirror.defineMode("asciiarmor", function() {
|
||||
return {
|
||||
token: function(stream, state) {
|
||||
var m;
|
||||
if (state.state == "top") {
|
||||
if (stream.sol() && (m = stream.match(/^-----BEGIN (.*)?-----\s*$/))) {
|
||||
state.state = "headers";
|
||||
state.type = m[1];
|
||||
return "tag";
|
||||
}
|
||||
return errorIfNotEmpty(stream);
|
||||
} else if (state.state == "headers") {
|
||||
if (stream.sol() && stream.match(/^\w+:/)) {
|
||||
state.state = "header";
|
||||
return "atom";
|
||||
} else {
|
||||
var result = errorIfNotEmpty(stream);
|
||||
if (result) state.state = "body";
|
||||
return result;
|
||||
}
|
||||
} else if (state.state == "header") {
|
||||
stream.skipToEnd();
|
||||
state.state = "headers";
|
||||
return "string";
|
||||
} else if (state.state == "body") {
|
||||
if (stream.sol() && (m = stream.match(/^-----END (.*)?-----\s*$/))) {
|
||||
if (m[1] != state.type) return "error";
|
||||
state.state = "end";
|
||||
return "tag";
|
||||
} else {
|
||||
if (stream.eatWhile(/[A-Za-z0-9+\/=]/)) {
|
||||
return null;
|
||||
} else {
|
||||
stream.next();
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
} else if (state.state == "end") {
|
||||
return errorIfNotEmpty(stream);
|
||||
}
|
||||
},
|
||||
blankLine: function(state) {
|
||||
if (state.state == "headers") state.state = "body";
|
||||
},
|
||||
startState: function() {
|
||||
return {state: "top", type: null};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("application/pgp", "asciiarmor");
|
||||
CodeMirror.defineMIME("application/pgp-keys", "asciiarmor");
|
||||
CodeMirror.defineMIME("application/pgp-signature", "asciiarmor");
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: ASCII Armor (PGP) mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="asciiarmor.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">ASCII Armor</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>ASCII Armor (PGP) mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
Version: OpenPrivacy 0.99
|
||||
|
||||
yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS
|
||||
vBSFjNSiVHsuAA==
|
||||
=njUN
|
||||
-----END PGP MESSAGE-----
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types
|
||||
defined:</strong> <code>application/pgp</code>, <code>application/pgp-keys</code>, <code>application/pgp-signature</code></p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,204 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("asn.1", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit,
|
||||
keywords = parserConfig.keywords || {},
|
||||
cmipVerbs = parserConfig.cmipVerbs || {},
|
||||
compareTypes = parserConfig.compareTypes || {},
|
||||
status = parserConfig.status || {},
|
||||
tags = parserConfig.tags || {},
|
||||
storage = parserConfig.storage || {},
|
||||
modifier = parserConfig.modifier || {},
|
||||
accessTypes = parserConfig.accessTypes|| {},
|
||||
multiLineStrings = parserConfig.multiLineStrings,
|
||||
indentStatements = parserConfig.indentStatements !== false;
|
||||
var isOperatorChar = /[\|\^]/;
|
||||
var curPunc;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (ch == '"' || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
if (/[\[\]\(\){}:=,;]/.test(ch)) {
|
||||
curPunc = ch;
|
||||
return "punctuation";
|
||||
}
|
||||
if (ch == "-"){
|
||||
if (stream.eat("-")) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
}
|
||||
if (/\d/.test(ch)) {
|
||||
stream.eatWhile(/[\w\.]/);
|
||||
return "number";
|
||||
}
|
||||
if (isOperatorChar.test(ch)) {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return "operator";
|
||||
}
|
||||
|
||||
stream.eatWhile(/[\w\-]/);
|
||||
var cur = stream.current();
|
||||
if (keywords.propertyIsEnumerable(cur)) return "keyword";
|
||||
if (cmipVerbs.propertyIsEnumerable(cur)) return "variable cmipVerbs";
|
||||
if (compareTypes.propertyIsEnumerable(cur)) return "atom compareTypes";
|
||||
if (status.propertyIsEnumerable(cur)) return "comment status";
|
||||
if (tags.propertyIsEnumerable(cur)) return "variable-3 tags";
|
||||
if (storage.propertyIsEnumerable(cur)) return "builtin storage";
|
||||
if (modifier.propertyIsEnumerable(cur)) return "string-2 modifier";
|
||||
if (accessTypes.propertyIsEnumerable(cur)) return "atom accessTypes";
|
||||
|
||||
return "variable";
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == quote && !escaped){
|
||||
var afterNext = stream.peek();
|
||||
//look if the character if the quote is like the B in '10100010'B
|
||||
if (afterNext){
|
||||
afterNext = afterNext.toLowerCase();
|
||||
if(afterNext == "b" || afterNext == "h" || afterNext == "o")
|
||||
stream.next();
|
||||
}
|
||||
end = true; break;
|
||||
}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
if (end || !(escaped || multiLineStrings))
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
function Context(indented, column, type, align, prev) {
|
||||
this.indented = indented;
|
||||
this.column = column;
|
||||
this.type = type;
|
||||
this.align = align;
|
||||
this.prev = prev;
|
||||
}
|
||||
function pushContext(state, col, type) {
|
||||
var indent = state.indented;
|
||||
if (state.context && state.context.type == "statement")
|
||||
indent = state.context.indented;
|
||||
return state.context = new Context(indent, col, type, null, state.context);
|
||||
}
|
||||
function popContext(state) {
|
||||
var t = state.context.type;
|
||||
if (t == ")" || t == "]" || t == "}")
|
||||
state.indented = state.context.indented;
|
||||
return state.context = state.context.prev;
|
||||
}
|
||||
|
||||
//Interface
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: null,
|
||||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
|
||||
indented: 0,
|
||||
startOfLine: true
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
var ctx = state.context;
|
||||
if (stream.sol()) {
|
||||
if (ctx.align == null) ctx.align = false;
|
||||
state.indented = stream.indentation();
|
||||
state.startOfLine = true;
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
curPunc = null;
|
||||
var style = (state.tokenize || tokenBase)(stream, state);
|
||||
if (style == "comment") return style;
|
||||
if (ctx.align == null) ctx.align = true;
|
||||
|
||||
if ((curPunc == ";" || curPunc == ":" || curPunc == ",")
|
||||
&& ctx.type == "statement"){
|
||||
popContext(state);
|
||||
}
|
||||
else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
||||
else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
||||
else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
||||
else if (curPunc == "}") {
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
if (ctx.type == "}") ctx = popContext(state);
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
}
|
||||
else if (curPunc == ctx.type) popContext(state);
|
||||
else if (indentStatements && (((ctx.type == "}" || ctx.type == "top")
|
||||
&& curPunc != ';') || (ctx.type == "statement"
|
||||
&& curPunc == "newstatement")))
|
||||
pushContext(state, stream.column(), "statement");
|
||||
|
||||
state.startOfLine = false;
|
||||
return style;
|
||||
},
|
||||
|
||||
electricChars: "{}",
|
||||
lineComment: "--",
|
||||
fold: "brace"
|
||||
};
|
||||
});
|
||||
|
||||
function words(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
CodeMirror.defineMIME("text/x-ttcn-asn", {
|
||||
name: "asn.1",
|
||||
keywords: words("DEFINITIONS OBJECTS IF DERIVED INFORMATION ACTION" +
|
||||
" REPLY ANY NAMED CHARACTERIZED BEHAVIOUR REGISTERED" +
|
||||
" WITH AS IDENTIFIED CONSTRAINED BY PRESENT BEGIN" +
|
||||
" IMPORTS FROM UNITS SYNTAX MIN-ACCESS MAX-ACCESS" +
|
||||
" MINACCESS MAXACCESS REVISION STATUS DESCRIPTION" +
|
||||
" SEQUENCE SET COMPONENTS OF CHOICE DistinguishedName" +
|
||||
" ENUMERATED SIZE MODULE END INDEX AUGMENTS EXTENSIBILITY" +
|
||||
" IMPLIED EXPORTS"),
|
||||
cmipVerbs: words("ACTIONS ADD GET NOTIFICATIONS REPLACE REMOVE"),
|
||||
compareTypes: words("OPTIONAL DEFAULT MANAGED MODULE-TYPE MODULE_IDENTITY" +
|
||||
" MODULE-COMPLIANCE OBJECT-TYPE OBJECT-IDENTITY" +
|
||||
" OBJECT-COMPLIANCE MODE CONFIRMED CONDITIONAL" +
|
||||
" SUBORDINATE SUPERIOR CLASS TRUE FALSE NULL" +
|
||||
" TEXTUAL-CONVENTION"),
|
||||
status: words("current deprecated mandatory obsolete"),
|
||||
tags: words("APPLICATION AUTOMATIC EXPLICIT IMPLICIT PRIVATE TAGS" +
|
||||
" UNIVERSAL"),
|
||||
storage: words("BOOLEAN INTEGER OBJECT IDENTIFIER BIT OCTET STRING" +
|
||||
" UTCTime InterfaceIndex IANAifType CMIP-Attribute" +
|
||||
" REAL PACKAGE PACKAGES IpAddress PhysAddress" +
|
||||
" NetworkAddress BITS BMPString TimeStamp TimeTicks" +
|
||||
" TruthValue RowStatus DisplayString GeneralString" +
|
||||
" GraphicString IA5String NumericString" +
|
||||
" PrintableString SnmpAdminAtring TeletexString" +
|
||||
" UTF8String VideotexString VisibleString StringStore" +
|
||||
" ISO646String T61String UniversalString Unsigned32" +
|
||||
" Integer32 Gauge Gauge32 Counter Counter32 Counter64"),
|
||||
modifier: words("ATTRIBUTE ATTRIBUTES MANDATORY-GROUP MANDATORY-GROUPS" +
|
||||
" GROUP GROUPS ELEMENTS EQUALITY ORDERING SUBSTRINGS" +
|
||||
" DEFINED"),
|
||||
accessTypes: words("not-accessible accessible-for-notify read-only" +
|
||||
" read-create read-write"),
|
||||
multiLineStrings: true
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: ASN.1 mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="asn.1.js"></script>
|
||||
<style type="text/css">
|
||||
.CodeMirror {
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1>
|
||||
<img id=logo src="../../doc/logo.png">
|
||||
</a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One">ASN.1</a>
|
||||
</ul>
|
||||
</div>
|
||||
<article>
|
||||
<h2>ASN.1 example</h2>
|
||||
<div>
|
||||
<textarea id="ttcn-asn-code">
|
||||
--
|
||||
-- Sample ASN.1 Code
|
||||
--
|
||||
MyModule DEFINITIONS ::=
|
||||
BEGIN
|
||||
|
||||
MyTypes ::= SEQUENCE {
|
||||
myObjectId OBJECT IDENTIFIER,
|
||||
mySeqOf SEQUENCE OF MyInt,
|
||||
myBitString BIT STRING {
|
||||
muxToken(0),
|
||||
modemToken(1)
|
||||
}
|
||||
}
|
||||
|
||||
MyInt ::= INTEGER (0..65535)
|
||||
|
||||
END
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var ttcnEditor = CodeMirror.fromTextArea(document.getElementById("ttcn-asn-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-ttcn-asn"
|
||||
});
|
||||
ttcnEditor.setSize(400, 400);
|
||||
var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
|
||||
CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
|
||||
</script>
|
||||
<br/>
|
||||
<p><strong>Language:</strong> Abstract Syntax Notation One
|
||||
(<a href="http://www.itu.int/en/ITU-T/asn1/Pages/introduction.aspx">ASN.1</a>)
|
||||
</p>
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-ttcn-asn</code></p>
|
||||
|
||||
<br/>
|
||||
<p>The development of this mode has been sponsored by <a href="http://www.ericsson.com/">Ericsson
|
||||
</a>.</p>
|
||||
<p>Coded by Asmelash Tsegay Gebretsadkan </p>
|
||||
</article>
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: mode/asterisk/asterisk.js
|
||||
*
|
||||
* Description: CodeMirror mode for Asterisk dialplan
|
||||
*
|
||||
* Created: 05/17/2012 09:20:25 PM
|
||||
* Revision: none
|
||||
*
|
||||
* Author: Stas Kobzar (stas@modulis.ca),
|
||||
* Company: Modulis.ca Inc.
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("asterisk", function() {
|
||||
var atoms = ["exten", "same", "include","ignorepat","switch"],
|
||||
dpcmd = ["#include","#exec"],
|
||||
apps = [
|
||||
"addqueuemember","adsiprog","aelsub","agentlogin","agentmonitoroutgoing","agi",
|
||||
"alarmreceiver","amd","answer","authenticate","background","backgrounddetect",
|
||||
"bridge","busy","callcompletioncancel","callcompletionrequest","celgenuserevent",
|
||||
"changemonitor","chanisavail","channelredirect","chanspy","clearhash","confbridge",
|
||||
"congestion","continuewhile","controlplayback","dahdiacceptr2call","dahdibarge",
|
||||
"dahdiras","dahdiscan","dahdisendcallreroutingfacility","dahdisendkeypadfacility",
|
||||
"datetime","dbdel","dbdeltree","deadagi","dial","dictate","directory","disa",
|
||||
"dumpchan","eagi","echo","endwhile","exec","execif","execiftime","exitwhile","extenspy",
|
||||
"externalivr","festival","flash","followme","forkcdr","getcpeid","gosub","gosubif",
|
||||
"goto","gotoif","gotoiftime","hangup","iax2provision","ices","importvar","incomplete",
|
||||
"ivrdemo","jabberjoin","jabberleave","jabbersend","jabbersendgroup","jabberstatus",
|
||||
"jack","log","macro","macroexclusive","macroexit","macroif","mailboxexists","meetme",
|
||||
"meetmeadmin","meetmechanneladmin","meetmecount","milliwatt","minivmaccmess","minivmdelete",
|
||||
"minivmgreet","minivmmwi","minivmnotify","minivmrecord","mixmonitor","monitor","morsecode",
|
||||
"mp3player","mset","musiconhold","nbscat","nocdr","noop","odbc","odbc","odbcfinish",
|
||||
"originate","ospauth","ospfinish","osplookup","ospnext","page","park","parkandannounce",
|
||||
"parkedcall","pausemonitor","pausequeuemember","pickup","pickupchan","playback","playtones",
|
||||
"privacymanager","proceeding","progress","queue","queuelog","raiseexception","read","readexten",
|
||||
"readfile","receivefax","receivefax","receivefax","record","removequeuemember",
|
||||
"resetcdr","retrydial","return","ringing","sayalpha","saycountedadj","saycountednoun",
|
||||
"saycountpl","saydigits","saynumber","sayphonetic","sayunixtime","senddtmf","sendfax",
|
||||
"sendfax","sendfax","sendimage","sendtext","sendurl","set","setamaflags",
|
||||
"setcallerpres","setmusiconhold","sipaddheader","sipdtmfmode","sipremoveheader","skel",
|
||||
"slastation","slatrunk","sms","softhangup","speechactivategrammar","speechbackground",
|
||||
"speechcreate","speechdeactivategrammar","speechdestroy","speechloadgrammar","speechprocessingsound",
|
||||
"speechstart","speechunloadgrammar","stackpop","startmusiconhold","stopmixmonitor","stopmonitor",
|
||||
"stopmusiconhold","stopplaytones","system","testclient","testserver","transfer","tryexec",
|
||||
"trysystem","unpausemonitor","unpausequeuemember","userevent","verbose","vmauthenticate",
|
||||
"vmsayname","voicemail","voicemailmain","wait","waitexten","waitfornoise","waitforring",
|
||||
"waitforsilence","waitmusiconhold","waituntil","while","zapateller"
|
||||
];
|
||||
|
||||
function basicToken(stream,state){
|
||||
var cur = '';
|
||||
var ch = stream.next();
|
||||
// comment
|
||||
if(ch == ";") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
// context
|
||||
if(ch == '[') {
|
||||
stream.skipTo(']');
|
||||
stream.eat(']');
|
||||
return "header";
|
||||
}
|
||||
// string
|
||||
if(ch == '"') {
|
||||
stream.skipTo('"');
|
||||
return "string";
|
||||
}
|
||||
if(ch == "'") {
|
||||
stream.skipTo("'");
|
||||
return "string-2";
|
||||
}
|
||||
// dialplan commands
|
||||
if(ch == '#') {
|
||||
stream.eatWhile(/\w/);
|
||||
cur = stream.current();
|
||||
if(dpcmd.indexOf(cur) !== -1) {
|
||||
stream.skipToEnd();
|
||||
return "strong";
|
||||
}
|
||||
}
|
||||
// application args
|
||||
if(ch == '$'){
|
||||
var ch1 = stream.peek();
|
||||
if(ch1 == '{'){
|
||||
stream.skipTo('}');
|
||||
stream.eat('}');
|
||||
return "variable-3";
|
||||
}
|
||||
}
|
||||
// extension
|
||||
stream.eatWhile(/\w/);
|
||||
cur = stream.current();
|
||||
if(atoms.indexOf(cur) !== -1) {
|
||||
state.extenStart = true;
|
||||
switch(cur) {
|
||||
case 'same': state.extenSame = true; break;
|
||||
case 'include':
|
||||
case 'switch':
|
||||
case 'ignorepat':
|
||||
state.extenInclude = true;break;
|
||||
default:break;
|
||||
}
|
||||
return "atom";
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
extenStart: false,
|
||||
extenSame: false,
|
||||
extenInclude: false,
|
||||
extenExten: false,
|
||||
extenPriority: false,
|
||||
extenApplication: false
|
||||
};
|
||||
},
|
||||
token: function(stream, state) {
|
||||
|
||||
var cur = '';
|
||||
if(stream.eatSpace()) return null;
|
||||
// extension started
|
||||
if(state.extenStart){
|
||||
stream.eatWhile(/[^\s]/);
|
||||
cur = stream.current();
|
||||
if(/^=>?$/.test(cur)){
|
||||
state.extenExten = true;
|
||||
state.extenStart = false;
|
||||
return "strong";
|
||||
} else {
|
||||
state.extenStart = false;
|
||||
stream.skipToEnd();
|
||||
return "error";
|
||||
}
|
||||
} else if(state.extenExten) {
|
||||
// set exten and priority
|
||||
state.extenExten = false;
|
||||
state.extenPriority = true;
|
||||
stream.eatWhile(/[^,]/);
|
||||
if(state.extenInclude) {
|
||||
stream.skipToEnd();
|
||||
state.extenPriority = false;
|
||||
state.extenInclude = false;
|
||||
}
|
||||
if(state.extenSame) {
|
||||
state.extenPriority = false;
|
||||
state.extenSame = false;
|
||||
state.extenApplication = true;
|
||||
}
|
||||
return "tag";
|
||||
} else if(state.extenPriority) {
|
||||
state.extenPriority = false;
|
||||
state.extenApplication = true;
|
||||
stream.next(); // get comma
|
||||
if(state.extenSame) return null;
|
||||
stream.eatWhile(/[^,]/);
|
||||
return "number";
|
||||
} else if(state.extenApplication) {
|
||||
stream.eatWhile(/,/);
|
||||
cur = stream.current();
|
||||
if(cur === ',') return null;
|
||||
stream.eatWhile(/\w/);
|
||||
cur = stream.current().toLowerCase();
|
||||
state.extenApplication = false;
|
||||
if(apps.indexOf(cur) !== -1){
|
||||
return "def strong";
|
||||
}
|
||||
} else{
|
||||
return basicToken(stream,state);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-asterisk", "asterisk");
|
||||
|
||||
});
|
||||
@@ -0,0 +1,154 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Asterisk dialplan mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="asterisk.js"></script>
|
||||
<style>
|
||||
.CodeMirror {border: 1px solid #999;}
|
||||
.cm-s-default span.cm-arrow { color: red; }
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Asterisk dialplan</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Asterisk dialplan mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
; extensions.conf - the Asterisk dial plan
|
||||
;
|
||||
|
||||
[general]
|
||||
;
|
||||
; If static is set to no, or omitted, then the pbx_config will rewrite
|
||||
; this file when extensions are modified. Remember that all comments
|
||||
; made in the file will be lost when that happens.
|
||||
static=yes
|
||||
|
||||
#include "/etc/asterisk/additional_general.conf
|
||||
|
||||
[iaxprovider]
|
||||
switch => IAX2/user:[key]@myserver/mycontext
|
||||
|
||||
[dynamic]
|
||||
#exec /usr/bin/dynamic-peers.pl
|
||||
|
||||
[trunkint]
|
||||
;
|
||||
; International long distance through trunk
|
||||
;
|
||||
exten => _9011.,1,Macro(dundi-e164,${EXTEN:4})
|
||||
exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})})
|
||||
|
||||
[local]
|
||||
;
|
||||
; Master context for local, toll-free, and iaxtel calls only
|
||||
;
|
||||
ignorepat => 9
|
||||
include => default
|
||||
|
||||
[demo]
|
||||
include => stdexten
|
||||
;
|
||||
; We start with what to do when a call first comes in.
|
||||
;
|
||||
exten => s,1,Wait(1) ; Wait a second, just for fun
|
||||
same => n,Answer ; Answer the line
|
||||
same => n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
|
||||
same => n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
|
||||
same => n(restart),BackGround(demo-congrats) ; Play a congratulatory message
|
||||
same => n(instruct),BackGround(demo-instruct) ; Play some instructions
|
||||
same => n,WaitExten ; Wait for an extension to be dialed.
|
||||
|
||||
exten => 2,1,BackGround(demo-moreinfo) ; Give some more information.
|
||||
exten => 2,n,Goto(s,instruct)
|
||||
|
||||
exten => 3,1,Set(LANGUAGE()=fr) ; Set language to french
|
||||
exten => 3,n,Goto(s,restart) ; Start with the congratulations
|
||||
|
||||
exten => 1000,1,Goto(default,s,1)
|
||||
;
|
||||
; We also create an example user, 1234, who is on the console and has
|
||||
; voicemail, etc.
|
||||
;
|
||||
exten => 1234,1,Playback(transfer,skip) ; "Please hold while..."
|
||||
; (but skip if channel is not up)
|
||||
exten => 1234,n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)}))
|
||||
exten => 1234,n,Goto(default,s,1) ; exited Voicemail
|
||||
|
||||
exten => 1235,1,Voicemail(1234,u) ; Right to voicemail
|
||||
|
||||
exten => 1236,1,Dial(Console/dsp) ; Ring forever
|
||||
exten => 1236,n,Voicemail(1234,b) ; Unless busy
|
||||
|
||||
;
|
||||
; # for when they're done with the demo
|
||||
;
|
||||
exten => #,1,Playback(demo-thanks) ; "Thanks for trying the demo"
|
||||
exten => #,n,Hangup ; Hang them up.
|
||||
|
||||
;
|
||||
; A timeout and "invalid extension rule"
|
||||
;
|
||||
exten => t,1,Goto(#,1) ; If they take too long, give up
|
||||
exten => i,1,Playback(invalid) ; "That's not valid, try again"
|
||||
|
||||
;
|
||||
; Create an extension, 500, for dialing the
|
||||
; Asterisk demo.
|
||||
;
|
||||
exten => 500,1,Playback(demo-abouttotry); Let them know what's going on
|
||||
exten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default) ; Call the Asterisk demo
|
||||
exten => 500,n,Playback(demo-nogo) ; Couldn't connect to the demo site
|
||||
exten => 500,n,Goto(s,6) ; Return to the start over message.
|
||||
|
||||
;
|
||||
; Create an extension, 600, for evaluating echo latency.
|
||||
;
|
||||
exten => 600,1,Playback(demo-echotest) ; Let them know what's going on
|
||||
exten => 600,n,Echo ; Do the echo test
|
||||
exten => 600,n,Playback(demo-echodone) ; Let them know it's over
|
||||
exten => 600,n,Goto(s,6) ; Start over
|
||||
|
||||
;
|
||||
; You can use the Macro Page to intercom a individual user
|
||||
exten => 76245,1,Macro(page,SIP/Grandstream1)
|
||||
; or if your peernames are the same as extensions
|
||||
exten => _7XXX,1,Macro(page,SIP/${EXTEN})
|
||||
;
|
||||
;
|
||||
; System Wide Page at extension 7999
|
||||
;
|
||||
exten => 7999,1,Set(TIMEOUT(absolute)=60)
|
||||
exten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)
|
||||
|
||||
; Give voicemail at extension 8500
|
||||
;
|
||||
exten => 8500,1,VoicemailMain
|
||||
exten => 8500,n,Goto(s,6)
|
||||
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: "text/x-asterisk",
|
||||
matchBrackets: true,
|
||||
lineNumber: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-asterisk</code>.</p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,85 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// Brainfuck mode created by Michael Kaminsky https://github.com/mkaminsky11
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object")
|
||||
mod(require("../../lib/codemirror"))
|
||||
else if (typeof define == "function" && define.amd)
|
||||
define(["../../lib/codemirror"], mod)
|
||||
else
|
||||
mod(CodeMirror)
|
||||
})(function(CodeMirror) {
|
||||
"use strict"
|
||||
var reserve = "><+-.,[]".split("");
|
||||
/*
|
||||
comments can be either:
|
||||
placed behind lines
|
||||
|
||||
+++ this is a comment
|
||||
|
||||
where reserved characters cannot be used
|
||||
or in a loop
|
||||
[
|
||||
this is ok to use [ ] and stuff
|
||||
]
|
||||
or preceded by #
|
||||
*/
|
||||
CodeMirror.defineMode("brainfuck", function() {
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
commentLine: false,
|
||||
left: 0,
|
||||
right: 0,
|
||||
commentLoop: false
|
||||
}
|
||||
},
|
||||
token: function(stream, state) {
|
||||
if (stream.eatSpace()) return null
|
||||
if(stream.sol()){
|
||||
state.commentLine = false;
|
||||
}
|
||||
var ch = stream.next().toString();
|
||||
if(reserve.indexOf(ch) !== -1){
|
||||
if(state.commentLine === true){
|
||||
if(stream.eol()){
|
||||
state.commentLine = false;
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
if(ch === "]" || ch === "["){
|
||||
if(ch === "["){
|
||||
state.left++;
|
||||
}
|
||||
else{
|
||||
state.right++;
|
||||
}
|
||||
return "bracket";
|
||||
}
|
||||
else if(ch === "+" || ch === "-"){
|
||||
return "keyword";
|
||||
}
|
||||
else if(ch === "<" || ch === ">"){
|
||||
return "atom";
|
||||
}
|
||||
else if(ch === "." || ch === ","){
|
||||
return "def";
|
||||
}
|
||||
}
|
||||
else{
|
||||
state.commentLine = true;
|
||||
if(stream.eol()){
|
||||
state.commentLine = false;
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
if(stream.eol()){
|
||||
state.commentLine = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
CodeMirror.defineMIME("text/x-brainfuck","brainfuck")
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Brainfuck mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="./brainfuck.js"></script>
|
||||
<style>
|
||||
.CodeMirror { border: 2px inset #dee; }
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#"></a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Brainfuck mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
[ This program prints "Hello World!" and a newline to the screen, its
|
||||
length is 106 active command characters [it is not the shortest.]
|
||||
|
||||
This loop is a "comment loop", it's a simple way of adding a comment
|
||||
to a BF program such that you don't have to worry about any command
|
||||
characters. Any ".", ",", "+", "-", "<" and ">" characters are simply
|
||||
ignored, the "[" and "]" characters just have to be balanced.
|
||||
]
|
||||
+++++ +++ Set Cell #0 to 8
|
||||
[
|
||||
>++++ Add 4 to Cell #1; this will always set Cell #1 to 4
|
||||
[ as the cell will be cleared by the loop
|
||||
>++ Add 2 to Cell #2
|
||||
>+++ Add 3 to Cell #3
|
||||
>+++ Add 3 to Cell #4
|
||||
>+ Add 1 to Cell #5
|
||||
<<<<- Decrement the loop counter in Cell #1
|
||||
] Loop till Cell #1 is zero; number of iterations is 4
|
||||
>+ Add 1 to Cell #2
|
||||
>+ Add 1 to Cell #3
|
||||
>- Subtract 1 from Cell #4
|
||||
>>+ Add 1 to Cell #6
|
||||
[<] Move back to the first zero cell you find; this will
|
||||
be Cell #1 which was cleared by the previous loop
|
||||
<- Decrement the loop Counter in Cell #0
|
||||
] Loop till Cell #0 is zero; number of iterations is 8
|
||||
|
||||
The result of this is:
|
||||
Cell No : 0 1 2 3 4 5 6
|
||||
Contents: 0 0 72 104 88 32 8
|
||||
Pointer : ^
|
||||
|
||||
>>. Cell #2 has value 72 which is 'H'
|
||||
>---. Subtract 3 from Cell #3 to get 101 which is 'e'
|
||||
+++++++..+++. Likewise for 'llo' from Cell #3
|
||||
>>. Cell #5 is 32 for the space
|
||||
<-. Subtract 1 from Cell #4 for 87 to give a 'W'
|
||||
<. Cell #3 was set to 'o' from the end of 'Hello'
|
||||
+++.------.--------. Cell #3 for 'rl' and 'd'
|
||||
>>+. Add 1 to Cell #5 gives us an exclamation point
|
||||
>++. And finally a newline from Cell #6
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-brainfuck"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>A mode for Brainfuck</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-brainfuck</code></p>
|
||||
</article>
|
||||
@@ -0,0 +1,786 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
function Context(indented, column, type, info, align, prev) {
|
||||
this.indented = indented;
|
||||
this.column = column;
|
||||
this.type = type;
|
||||
this.info = info;
|
||||
this.align = align;
|
||||
this.prev = prev;
|
||||
}
|
||||
function pushContext(state, col, type, info) {
|
||||
var indent = state.indented;
|
||||
if (state.context && state.context.type != "statement" && type != "statement")
|
||||
indent = state.context.indented;
|
||||
return state.context = new Context(indent, col, type, info, null, state.context);
|
||||
}
|
||||
function popContext(state) {
|
||||
var t = state.context.type;
|
||||
if (t == ")" || t == "]" || t == "}")
|
||||
state.indented = state.context.indented;
|
||||
return state.context = state.context.prev;
|
||||
}
|
||||
|
||||
function typeBefore(stream, state, pos) {
|
||||
if (state.prevToken == "variable" || state.prevToken == "variable-3") return true;
|
||||
if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true;
|
||||
if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;
|
||||
}
|
||||
|
||||
function isTopScope(context) {
|
||||
for (;;) {
|
||||
if (!context || context.type == "top") return true;
|
||||
if (context.type == "}" && context.prev.info != "namespace") return false;
|
||||
context = context.prev;
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.defineMode("clike", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit,
|
||||
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
|
||||
dontAlignCalls = parserConfig.dontAlignCalls,
|
||||
keywords = parserConfig.keywords || {},
|
||||
types = parserConfig.types || {},
|
||||
builtin = parserConfig.builtin || {},
|
||||
blockKeywords = parserConfig.blockKeywords || {},
|
||||
defKeywords = parserConfig.defKeywords || {},
|
||||
atoms = parserConfig.atoms || {},
|
||||
hooks = parserConfig.hooks || {},
|
||||
multiLineStrings = parserConfig.multiLineStrings,
|
||||
indentStatements = parserConfig.indentStatements !== false,
|
||||
indentSwitch = parserConfig.indentSwitch !== false,
|
||||
namespaceSeparator = parserConfig.namespaceSeparator,
|
||||
isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
|
||||
numberStart = parserConfig.numberStart || /[\d\.]/,
|
||||
number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,
|
||||
isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
|
||||
endStatement = parserConfig.endStatement || /^[;:,]$/;
|
||||
|
||||
var curPunc, isDefKeyword;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (hooks[ch]) {
|
||||
var result = hooks[ch](stream, state);
|
||||
if (result !== false) return result;
|
||||
}
|
||||
if (ch == '"' || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
if (isPunctuationChar.test(ch)) {
|
||||
curPunc = ch;
|
||||
return null;
|
||||
}
|
||||
if (numberStart.test(ch)) {
|
||||
stream.backUp(1)
|
||||
if (stream.match(number)) return "number"
|
||||
stream.next()
|
||||
}
|
||||
if (ch == "/") {
|
||||
if (stream.eat("*")) {
|
||||
state.tokenize = tokenComment;
|
||||
return tokenComment(stream, state);
|
||||
}
|
||||
if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
}
|
||||
if (isOperatorChar.test(ch)) {
|
||||
while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {}
|
||||
return "operator";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
if (namespaceSeparator) while (stream.match(namespaceSeparator))
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
|
||||
var cur = stream.current();
|
||||
if (contains(keywords, cur)) {
|
||||
if (contains(blockKeywords, cur)) curPunc = "newstatement";
|
||||
if (contains(defKeywords, cur)) isDefKeyword = true;
|
||||
return "keyword";
|
||||
}
|
||||
if (contains(types, cur)) return "variable-3";
|
||||
if (contains(builtin, cur)) {
|
||||
if (contains(blockKeywords, cur)) curPunc = "newstatement";
|
||||
return "builtin";
|
||||
}
|
||||
if (contains(atoms, cur)) return "atom";
|
||||
return "variable";
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == quote && !escaped) {end = true; break;}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
if (end || !(escaped || multiLineStrings))
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
function tokenComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "/" && maybeEnd) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
|
||||
function maybeEOL(stream, state) {
|
||||
if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
|
||||
state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: null,
|
||||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false),
|
||||
indented: 0,
|
||||
startOfLine: true,
|
||||
prevToken: null
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
var ctx = state.context;
|
||||
if (stream.sol()) {
|
||||
if (ctx.align == null) ctx.align = false;
|
||||
state.indented = stream.indentation();
|
||||
state.startOfLine = true;
|
||||
}
|
||||
if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
|
||||
curPunc = isDefKeyword = null;
|
||||
var style = (state.tokenize || tokenBase)(stream, state);
|
||||
if (style == "comment" || style == "meta") return style;
|
||||
if (ctx.align == null) ctx.align = true;
|
||||
|
||||
if (endStatement.test(curPunc)) while (state.context.type == "statement") popContext(state);
|
||||
else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
||||
else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
||||
else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
||||
else if (curPunc == "}") {
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
if (ctx.type == "}") ctx = popContext(state);
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
}
|
||||
else if (curPunc == ctx.type) popContext(state);
|
||||
else if (indentStatements &&
|
||||
(((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
|
||||
(ctx.type == "statement" && curPunc == "newstatement"))) {
|
||||
pushContext(state, stream.column(), "statement", stream.current());
|
||||
}
|
||||
|
||||
if (style == "variable" &&
|
||||
((state.prevToken == "def" ||
|
||||
(parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&
|
||||
isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
|
||||
style = "def";
|
||||
|
||||
if (hooks.token) {
|
||||
var result = hooks.token(stream, state, style);
|
||||
if (result !== undefined) style = result;
|
||||
}
|
||||
|
||||
if (style == "def" && parserConfig.styleDefs === false) style = "variable";
|
||||
|
||||
state.startOfLine = false;
|
||||
state.prevToken = isDefKeyword ? "def" : style || curPunc;
|
||||
maybeEOL(stream, state);
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
|
||||
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
|
||||
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
|
||||
if (parserConfig.dontIndentStatements)
|
||||
while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
|
||||
ctx = ctx.prev
|
||||
if (hooks.indent) {
|
||||
var hook = hooks.indent(state, ctx, textAfter);
|
||||
if (typeof hook == "number") return hook
|
||||
}
|
||||
var closing = firstChar == ctx.type;
|
||||
var switchBlock = ctx.prev && ctx.prev.info == "switch";
|
||||
if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
|
||||
while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
|
||||
return ctx.indented
|
||||
}
|
||||
if (ctx.type == "statement")
|
||||
return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
|
||||
if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
|
||||
return ctx.column + (closing ? 0 : 1);
|
||||
if (ctx.type == ")" && !closing)
|
||||
return ctx.indented + statementIndentUnit;
|
||||
|
||||
return ctx.indented + (closing ? 0 : indentUnit) +
|
||||
(!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
|
||||
},
|
||||
|
||||
electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
|
||||
blockCommentStart: "/*",
|
||||
blockCommentEnd: "*/",
|
||||
lineComment: "//",
|
||||
fold: "brace"
|
||||
};
|
||||
});
|
||||
|
||||
function words(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
function contains(words, word) {
|
||||
if (typeof words === "function") {
|
||||
return words(word);
|
||||
} else {
|
||||
return words.propertyIsEnumerable(word);
|
||||
}
|
||||
}
|
||||
var cKeywords = "auto if break case register continue return default do sizeof " +
|
||||
"static else struct switch extern typedef union for goto while enum const volatile";
|
||||
var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t";
|
||||
|
||||
function cppHook(stream, state) {
|
||||
if (!state.startOfLine) return false
|
||||
for (var ch, next = null; ch = stream.peek();) {
|
||||
if (ch == "\\" && stream.match(/^.$/)) {
|
||||
next = cppHook
|
||||
break
|
||||
} else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) {
|
||||
break
|
||||
}
|
||||
stream.next()
|
||||
}
|
||||
state.tokenize = next
|
||||
return "meta"
|
||||
}
|
||||
|
||||
function pointerHook(_stream, state) {
|
||||
if (state.prevToken == "variable-3") return "variable-3";
|
||||
return false;
|
||||
}
|
||||
|
||||
function cpp14Literal(stream) {
|
||||
stream.eatWhile(/[\w\.']/);
|
||||
return "number";
|
||||
}
|
||||
|
||||
function cpp11StringHook(stream, state) {
|
||||
stream.backUp(1);
|
||||
// Raw strings.
|
||||
if (stream.match(/(R|u8R|uR|UR|LR)/)) {
|
||||
var match = stream.match(/"([^\s\\()]{0,16})\(/);
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
state.cpp11RawStringDelim = match[1];
|
||||
state.tokenize = tokenRawString;
|
||||
return tokenRawString(stream, state);
|
||||
}
|
||||
// Unicode strings/chars.
|
||||
if (stream.match(/(u8|u|U|L)/)) {
|
||||
if (stream.match(/["']/, /* eat */ false)) {
|
||||
return "string";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Ignore this hook.
|
||||
stream.next();
|
||||
return false;
|
||||
}
|
||||
|
||||
function cppLooksLikeConstructor(word) {
|
||||
var lastTwo = /(\w+)::(\w+)$/.exec(word);
|
||||
return lastTwo && lastTwo[1] == lastTwo[2];
|
||||
}
|
||||
|
||||
// C#-style strings where "" escapes a quote.
|
||||
function tokenAtString(stream, state) {
|
||||
var next;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == '"' && !stream.eat('"')) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
// C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
|
||||
// <delim> can be a string up to 16 characters long.
|
||||
function tokenRawString(stream, state) {
|
||||
// Escape characters that have special regex meanings.
|
||||
var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
|
||||
var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
|
||||
if (match)
|
||||
state.tokenize = null;
|
||||
else
|
||||
stream.skipToEnd();
|
||||
return "string";
|
||||
}
|
||||
|
||||
function def(mimes, mode) {
|
||||
if (typeof mimes == "string") mimes = [mimes];
|
||||
var words = [];
|
||||
function add(obj) {
|
||||
if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
|
||||
words.push(prop);
|
||||
}
|
||||
add(mode.keywords);
|
||||
add(mode.types);
|
||||
add(mode.builtin);
|
||||
add(mode.atoms);
|
||||
if (words.length) {
|
||||
mode.helperType = mimes[0];
|
||||
CodeMirror.registerHelper("hintWords", mimes[0], words);
|
||||
}
|
||||
|
||||
for (var i = 0; i < mimes.length; ++i)
|
||||
CodeMirror.defineMIME(mimes[i], mode);
|
||||
}
|
||||
|
||||
def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords),
|
||||
types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " +
|
||||
"int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " +
|
||||
"uint32_t uint64_t"),
|
||||
blockKeywords: words("case do else for if switch while struct"),
|
||||
defKeywords: words("struct"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("null true false"),
|
||||
hooks: {"#": cppHook, "*": pointerHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def(["text/x-c++src", "text/x-c++hdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " +
|
||||
"static_cast typeid catch operator template typename class friend private " +
|
||||
"this using const_cast inline public throw virtual delete mutable protected " +
|
||||
"alignas alignof constexpr decltype nullptr noexcept thread_local final " +
|
||||
"static_assert override"),
|
||||
types: words(cTypes + " bool wchar_t"),
|
||||
blockKeywords: words("catch class do else finally for if struct switch try while"),
|
||||
defKeywords: words("class namespace struct enum union"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
dontIndentStatements: /^template$/,
|
||||
hooks: {
|
||||
"#": cppHook,
|
||||
"*": pointerHook,
|
||||
"u": cpp11StringHook,
|
||||
"U": cpp11StringHook,
|
||||
"L": cpp11StringHook,
|
||||
"R": cpp11StringHook,
|
||||
"0": cpp14Literal,
|
||||
"1": cpp14Literal,
|
||||
"2": cpp14Literal,
|
||||
"3": cpp14Literal,
|
||||
"4": cpp14Literal,
|
||||
"5": cpp14Literal,
|
||||
"6": cpp14Literal,
|
||||
"7": cpp14Literal,
|
||||
"8": cpp14Literal,
|
||||
"9": cpp14Literal,
|
||||
token: function(stream, state, style) {
|
||||
if (style == "variable" && stream.peek() == "(" &&
|
||||
(state.prevToken == ";" || state.prevToken == null ||
|
||||
state.prevToken == "}") &&
|
||||
cppLooksLikeConstructor(stream.current()))
|
||||
return "def";
|
||||
}
|
||||
},
|
||||
namespaceSeparator: "::",
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-java", {
|
||||
name: "clike",
|
||||
keywords: words("abstract assert break case catch class const continue default " +
|
||||
"do else enum extends final finally float for goto if implements import " +
|
||||
"instanceof interface native new package private protected public " +
|
||||
"return static strictfp super switch synchronized this throw throws transient " +
|
||||
"try volatile while"),
|
||||
types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " +
|
||||
"Integer Long Number Object Short String StringBuffer StringBuilder Void"),
|
||||
blockKeywords: words("catch class do else finally for if switch try while"),
|
||||
defKeywords: words("class interface package enum"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
endStatement: /^[;:]$/,
|
||||
number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
},
|
||||
modeProps: {fold: ["brace", "import"]}
|
||||
});
|
||||
|
||||
def("text/x-csharp", {
|
||||
name: "clike",
|
||||
keywords: words("abstract as async await base break case catch checked class const continue" +
|
||||
" default delegate do else enum event explicit extern finally fixed for" +
|
||||
" foreach goto if implicit in interface internal is lock namespace new" +
|
||||
" operator out override params private protected public readonly ref return sealed" +
|
||||
" sizeof stackalloc static struct switch this throw try typeof unchecked" +
|
||||
" unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
|
||||
" global group into join let orderby partial remove select set value var yield"),
|
||||
types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" +
|
||||
" Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" +
|
||||
" UInt64 bool byte char decimal double short int long object" +
|
||||
" sbyte float string ushort uint ulong"),
|
||||
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
|
||||
defKeywords: words("class interface namespace struct var"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream, state) {
|
||||
if (stream.eat('"')) {
|
||||
state.tokenize = tokenAtString;
|
||||
return tokenAtString(stream, state);
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function tokenTripleString(stream, state) {
|
||||
var escaped = false;
|
||||
while (!stream.eol()) {
|
||||
if (!escaped && stream.match('"""')) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
escaped = stream.next() == "\\" && !escaped;
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
def("text/x-scala", {
|
||||
name: "clike",
|
||||
keywords: words(
|
||||
|
||||
/* scala */
|
||||
"abstract case catch class def do else extends final finally for forSome if " +
|
||||
"implicit import lazy match new null object override package private protected return " +
|
||||
"sealed super this throw trait try type val var while with yield _ : = => <- <: " +
|
||||
"<% >: # @ " +
|
||||
|
||||
/* package scala */
|
||||
"assert assume require print println printf readLine readBoolean readByte readShort " +
|
||||
"readChar readInt readLong readFloat readDouble " +
|
||||
|
||||
":: #:: "
|
||||
),
|
||||
types: words(
|
||||
"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
|
||||
"Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable " +
|
||||
"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
|
||||
"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
|
||||
"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " +
|
||||
|
||||
/* package java.lang */
|
||||
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
|
||||
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
|
||||
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
|
||||
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
|
||||
),
|
||||
multiLineStrings: true,
|
||||
blockKeywords: words("catch class do else finally for forSome if match switch try while"),
|
||||
defKeywords: words("class def object package trait type val var"),
|
||||
atoms: words("true false null"),
|
||||
indentStatements: false,
|
||||
indentSwitch: false,
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
},
|
||||
'"': function(stream, state) {
|
||||
if (!stream.match('""')) return false;
|
||||
state.tokenize = tokenTripleString;
|
||||
return state.tokenize(stream, state);
|
||||
},
|
||||
"'": function(stream) {
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
return "atom";
|
||||
},
|
||||
"=": function(stream, state) {
|
||||
var cx = state.context
|
||||
if (cx.type == "}" && cx.align && stream.eat(">")) {
|
||||
state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)
|
||||
return "operator"
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
modeProps: {closeBrackets: {triples: '"'}}
|
||||
});
|
||||
|
||||
function tokenKotlinString(tripleString){
|
||||
return function (stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while (!stream.eol()) {
|
||||
if (!tripleString && !escaped && stream.match('"') ) {end = true; break;}
|
||||
if (tripleString && stream.match('"""')) {end = true; break;}
|
||||
next = stream.next();
|
||||
if(!escaped && next == "$" && stream.match('{'))
|
||||
stream.skipTo("}");
|
||||
escaped = !escaped && next == "\\" && !tripleString;
|
||||
}
|
||||
if (end || !tripleString)
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
}
|
||||
}
|
||||
|
||||
def("text/x-kotlin", {
|
||||
name: "clike",
|
||||
keywords: words(
|
||||
/*keywords*/
|
||||
"package as typealias class interface this super val " +
|
||||
"var fun for is in This throw return " +
|
||||
"break continue object if else while do try when !in !is as? " +
|
||||
|
||||
/*soft keywords*/
|
||||
"file import where by get set abstract enum open inner override private public internal " +
|
||||
"protected catch finally out final vararg reified dynamic companion constructor init " +
|
||||
"sealed field property receiver param sparam lateinit data inline noinline tailrec " +
|
||||
"external annotation crossinline const operator infix"
|
||||
),
|
||||
types: words(
|
||||
/* package java.lang */
|
||||
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
|
||||
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
|
||||
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
|
||||
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
|
||||
),
|
||||
intendSwitch: false,
|
||||
indentStatements: false,
|
||||
multiLineStrings: true,
|
||||
blockKeywords: words("catch class do else finally for if where try while enum"),
|
||||
defKeywords: words("class val var object package interface fun"),
|
||||
atoms: words("true false null this"),
|
||||
hooks: {
|
||||
'"': function(stream, state) {
|
||||
state.tokenize = tokenKotlinString(stream.match('""'));
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
},
|
||||
modeProps: {closeBrackets: {triples: '"'}}
|
||||
});
|
||||
|
||||
def(["x-shader/x-vertex", "x-shader/x-fragment"], {
|
||||
name: "clike",
|
||||
keywords: words("sampler1D sampler2D sampler3D samplerCube " +
|
||||
"sampler1DShadow sampler2DShadow " +
|
||||
"const attribute uniform varying " +
|
||||
"break continue discard return " +
|
||||
"for while do if else struct " +
|
||||
"in out inout"),
|
||||
types: words("float int bool void " +
|
||||
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
|
||||
"mat2 mat3 mat4"),
|
||||
blockKeywords: words("for while do if else struct"),
|
||||
builtin: words("radians degrees sin cos tan asin acos atan " +
|
||||
"pow exp log exp2 sqrt inversesqrt " +
|
||||
"abs sign floor ceil fract mod min max clamp mix step smoothstep " +
|
||||
"length distance dot cross normalize ftransform faceforward " +
|
||||
"reflect refract matrixCompMult " +
|
||||
"lessThan lessThanEqual greaterThan greaterThanEqual " +
|
||||
"equal notEqual any all not " +
|
||||
"texture1D texture1DProj texture1DLod texture1DProjLod " +
|
||||
"texture2D texture2DProj texture2DLod texture2DProjLod " +
|
||||
"texture3D texture3DProj texture3DLod texture3DProjLod " +
|
||||
"textureCube textureCubeLod " +
|
||||
"shadow1D shadow2D shadow1DProj shadow2DProj " +
|
||||
"shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
|
||||
"dFdx dFdy fwidth " +
|
||||
"noise1 noise2 noise3 noise4"),
|
||||
atoms: words("true false " +
|
||||
"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
|
||||
"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
|
||||
"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
|
||||
"gl_FogCoord gl_PointCoord " +
|
||||
"gl_Position gl_PointSize gl_ClipVertex " +
|
||||
"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
|
||||
"gl_TexCoord gl_FogFragCoord " +
|
||||
"gl_FragCoord gl_FrontFacing " +
|
||||
"gl_FragData gl_FragDepth " +
|
||||
"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
|
||||
"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
|
||||
"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
|
||||
"gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
|
||||
"gl_ProjectionMatrixInverseTranspose " +
|
||||
"gl_ModelViewProjectionMatrixInverseTranspose " +
|
||||
"gl_TextureMatrixInverseTranspose " +
|
||||
"gl_NormalScale gl_DepthRange gl_ClipPlane " +
|
||||
"gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
|
||||
"gl_FrontLightModelProduct gl_BackLightModelProduct " +
|
||||
"gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
|
||||
"gl_FogParameters " +
|
||||
"gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
|
||||
"gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
|
||||
"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
|
||||
"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
|
||||
"gl_MaxDrawBuffers"),
|
||||
indentSwitch: false,
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-nesc", {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
|
||||
"implementation includes interface module new norace nx_struct nx_union post provides " +
|
||||
"signal task uses abstract extends"),
|
||||
types: words(cTypes),
|
||||
blockKeywords: words("case do else for if switch while struct"),
|
||||
atoms: words("null true false"),
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-objectivec", {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in " +
|
||||
"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
|
||||
types: words(cTypes),
|
||||
atoms: words("YES NO NULL NILL ON OFF true false"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$]/);
|
||||
return "keyword";
|
||||
},
|
||||
"#": cppHook,
|
||||
indent: function(_state, ctx, textAfter) {
|
||||
if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
|
||||
}
|
||||
},
|
||||
modeProps: {fold: "brace"}
|
||||
});
|
||||
|
||||
def("text/x-squirrel", {
|
||||
name: "clike",
|
||||
keywords: words("base break clone continue const default delete enum extends function in class" +
|
||||
" foreach local resume return this throw typeof yield constructor instanceof static"),
|
||||
types: words(cTypes),
|
||||
blockKeywords: words("case catch class else for foreach if switch try while"),
|
||||
defKeywords: words("function local class"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
// Ceylon Strings need to deal with interpolation
|
||||
var stringTokenizer = null;
|
||||
function tokenCeylonString(type) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while (!stream.eol()) {
|
||||
if (!escaped && stream.match('"') &&
|
||||
(type == "single" || stream.match('""'))) {
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
if (!escaped && stream.match('``')) {
|
||||
stringTokenizer = tokenCeylonString(type);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
next = stream.next();
|
||||
escaped = type == "single" && !escaped && next == "\\";
|
||||
}
|
||||
if (end)
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
}
|
||||
}
|
||||
|
||||
def("text/x-ceylon", {
|
||||
name: "clike",
|
||||
keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
|
||||
" exists extends finally for function given if import in interface is let module new" +
|
||||
" nonempty object of out outer package return satisfies super switch then this throw" +
|
||||
" try value void while"),
|
||||
types: function(word) {
|
||||
// In Ceylon all identifiers that start with an uppercase are types
|
||||
var first = word.charAt(0);
|
||||
return (first === first.toUpperCase() && first !== first.toLowerCase());
|
||||
},
|
||||
blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
|
||||
defKeywords: words("class dynamic function interface module object package value"),
|
||||
builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
|
||||
" native optional sealed see serializable shared suppressWarnings tagged throws variable"),
|
||||
isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
|
||||
isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
|
||||
numberStart: /[\d#$]/,
|
||||
number: /^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,
|
||||
multiLineStrings: true,
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null larger smaller equal empty finished"),
|
||||
indentSwitch: false,
|
||||
styleDefs: false,
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
},
|
||||
'"': function(stream, state) {
|
||||
state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
|
||||
return state.tokenize(stream, state);
|
||||
},
|
||||
'`': function(stream, state) {
|
||||
if (!stringTokenizer || !stream.match('`')) return false;
|
||||
state.tokenize = stringTokenizer;
|
||||
stringTokenizer = null;
|
||||
return state.tokenize(stream, state);
|
||||
},
|
||||
"'": function(stream) {
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
return "atom";
|
||||
},
|
||||
token: function(_stream, state, style) {
|
||||
if ((style == "variable" || style == "variable-3") &&
|
||||
state.prevToken == ".") {
|
||||
return "variable-2";
|
||||
}
|
||||
}
|
||||
},
|
||||
modeProps: {
|
||||
fold: ["brace", "import"],
|
||||
closeBrackets: {triples: '"'}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,360 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: C-like mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<link rel="stylesheet" href="../../addon/hint/show-hint.css">
|
||||
<script src="../../addon/hint/show-hint.js"></script>
|
||||
<script src="clike.js"></script>
|
||||
<style>.CodeMirror {border: 2px inset #dee;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">C-like</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>C-like mode</h2>
|
||||
|
||||
<div><textarea id="c-code">
|
||||
/* C demo code */
|
||||
|
||||
#include <zmq.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
|
||||
typedef struct {
|
||||
void* arg_socket;
|
||||
zmq_msg_t* arg_msg;
|
||||
char* arg_string;
|
||||
unsigned long arg_len;
|
||||
int arg_int, arg_command;
|
||||
|
||||
int signal_fd;
|
||||
int pad;
|
||||
void* context;
|
||||
sem_t sem;
|
||||
} acl_zmq_context;
|
||||
|
||||
#define p(X) (context->arg_##X)
|
||||
|
||||
void* zmq_thread(void* context_pointer) {
|
||||
acl_zmq_context* context = (acl_zmq_context*)context_pointer;
|
||||
char ok = 'K', err = 'X';
|
||||
int res;
|
||||
|
||||
while (1) {
|
||||
while ((res = sem_wait(&context->sem)) == EINTR);
|
||||
if (res) {write(context->signal_fd, &err, 1); goto cleanup;}
|
||||
switch(p(command)) {
|
||||
case 0: goto cleanup;
|
||||
case 1: p(socket) = zmq_socket(context->context, p(int)); break;
|
||||
case 2: p(int) = zmq_close(p(socket)); break;
|
||||
case 3: p(int) = zmq_bind(p(socket), p(string)); break;
|
||||
case 4: p(int) = zmq_connect(p(socket), p(string)); break;
|
||||
case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &p(len)); break;
|
||||
case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;
|
||||
case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;
|
||||
case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;
|
||||
case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;
|
||||
}
|
||||
p(command) = errno;
|
||||
write(context->signal_fd, &ok, 1);
|
||||
}
|
||||
cleanup:
|
||||
close(context->signal_fd);
|
||||
free(context_pointer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* zmq_thread_init(void* zmq_context, int signal_fd) {
|
||||
acl_zmq_context* context = malloc(sizeof(acl_zmq_context));
|
||||
pthread_t thread;
|
||||
|
||||
context->context = zmq_context;
|
||||
context->signal_fd = signal_fd;
|
||||
sem_init(&context->sem, 1, 0);
|
||||
pthread_create(&thread, 0, &zmq_thread, context);
|
||||
pthread_detach(thread);
|
||||
return context;
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>C++ example</h2>
|
||||
|
||||
<div><textarea id="cpp-code">
|
||||
#include <iostream>
|
||||
#include "mystuff/util.h"
|
||||
|
||||
namespace {
|
||||
enum Enum {
|
||||
VAL1, VAL2, VAL3
|
||||
};
|
||||
|
||||
char32_t unicode_string = U"\U0010FFFF";
|
||||
string raw_string = R"delim(anything
|
||||
you
|
||||
want)delim";
|
||||
|
||||
int Helper(const MyType& param) {
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class ForwardDec;
|
||||
|
||||
template <class T, class V>
|
||||
class Class : public BaseClass {
|
||||
const MyType<T, V> member_;
|
||||
|
||||
public:
|
||||
const MyType<T, V>& Method() const {
|
||||
return member_;
|
||||
}
|
||||
|
||||
void Method2(MyType<T, V>* value);
|
||||
}
|
||||
|
||||
template <class T, class V>
|
||||
void Class::Method2(MyType<T, V>* value) {
|
||||
std::out << 1 >> method();
|
||||
value->Method3(member_);
|
||||
member_ = value;
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Objective-C example</h2>
|
||||
|
||||
<div><textarea id="objectivec-code">
|
||||
/*
|
||||
This is a longer comment
|
||||
That spans two lines
|
||||
*/
|
||||
|
||||
#import <Test/Test.h>
|
||||
@implementation YourAppDelegate
|
||||
|
||||
// This is a one-line comment
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
|
||||
char myString[] = "This is a C character array";
|
||||
int test = 5;
|
||||
return YES;
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Java example</h2>
|
||||
|
||||
<div><textarea id="java-code">
|
||||
import com.demo.util.MyType;
|
||||
import com.demo.util.MyInterface;
|
||||
|
||||
public enum Enum {
|
||||
VAL1, VAL2, VAL3
|
||||
}
|
||||
|
||||
public class Class<T, V> implements MyInterface {
|
||||
public static final MyType<T, V> member;
|
||||
|
||||
private class InnerClass {
|
||||
public int zero() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyType method() {
|
||||
return member;
|
||||
}
|
||||
|
||||
public void method2(MyType<T, V> value) {
|
||||
method();
|
||||
value.method3();
|
||||
member = value;
|
||||
}
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Scala example</h2>
|
||||
|
||||
<div><textarea id="scala-code">
|
||||
object FilterTest extends App {
|
||||
def filter(xs: List[Int], threshold: Int) = {
|
||||
def process(ys: List[Int]): List[Int] =
|
||||
if (ys.isEmpty) ys
|
||||
else if (ys.head < threshold) ys.head :: process(ys.tail)
|
||||
else process(ys.tail)
|
||||
process(xs)
|
||||
}
|
||||
println(filter(List(1, 9, 2, 8, 3, 7, 4), 5))
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Kotlin mode</h2>
|
||||
|
||||
<div><textarea id="kotlin-code">
|
||||
package org.wasabi.http
|
||||
|
||||
import java.util.concurrent.Executors
|
||||
import java.net.InetSocketAddress
|
||||
import org.wasabi.app.AppConfiguration
|
||||
import io.netty.bootstrap.ServerBootstrap
|
||||
import io.netty.channel.nio.NioEventLoopGroup
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel
|
||||
import org.wasabi.app.AppServer
|
||||
|
||||
public class HttpServer(private val appServer: AppServer) {
|
||||
|
||||
val bootstrap: ServerBootstrap
|
||||
val primaryGroup: NioEventLoopGroup
|
||||
val workerGroup: NioEventLoopGroup
|
||||
|
||||
init {
|
||||
// Define worker groups
|
||||
primaryGroup = NioEventLoopGroup()
|
||||
workerGroup = NioEventLoopGroup()
|
||||
|
||||
// Initialize bootstrap of server
|
||||
bootstrap = ServerBootstrap()
|
||||
|
||||
bootstrap.group(primaryGroup, workerGroup)
|
||||
bootstrap.channel(javaClass<NioServerSocketChannel>())
|
||||
bootstrap.childHandler(NettyPipelineInitializer(appServer))
|
||||
}
|
||||
|
||||
public fun start(wait: Boolean = true) {
|
||||
val channel = bootstrap.bind(appServer.configuration.port)?.sync()?.channel()
|
||||
|
||||
if (wait) {
|
||||
channel?.closeFuture()?.sync()
|
||||
}
|
||||
}
|
||||
|
||||
public fun stop() {
|
||||
// Shutdown all event loops
|
||||
primaryGroup.shutdownGracefully()
|
||||
workerGroup.shutdownGracefully()
|
||||
|
||||
// Wait till all threads are terminated
|
||||
primaryGroup.terminationFuture().sync()
|
||||
workerGroup.terminationFuture().sync()
|
||||
}
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Ceylon mode</h2>
|
||||
|
||||
<div><textarea id="ceylon-code">
|
||||
"Produces the [[stream|Iterable]] that results from repeated
|
||||
application of the given [[function|next]] to the given
|
||||
[[first]] element of the stream, until the function first
|
||||
returns [[finished]]. If the given function never returns
|
||||
`finished`, the resulting stream is infinite.
|
||||
|
||||
For example:
|
||||
|
||||
loop(0)(2.plus).takeWhile(10.largerThan)
|
||||
|
||||
produces the stream `{ 0, 2, 4, 6, 8 }`."
|
||||
tagged("Streams")
|
||||
shared {Element+} loop<Element>(
|
||||
"The first element of the resulting stream."
|
||||
Element first)(
|
||||
"The function that produces the next element of the
|
||||
stream, given the current element. The function may
|
||||
return [[finished]] to indicate the end of the
|
||||
stream."
|
||||
Element|Finished next(Element element))
|
||||
=> let (start = first)
|
||||
object satisfies {Element+} {
|
||||
first => start;
|
||||
empty => false;
|
||||
function nextElement(Element element)
|
||||
=> next(element);
|
||||
iterator()
|
||||
=> object satisfies Iterator<Element> {
|
||||
variable Element|Finished current = start;
|
||||
shared actual Element|Finished next() {
|
||||
if (!is Finished result = current) {
|
||||
current = nextElement(result);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return finished;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
</textarea></div>
|
||||
|
||||
<script>
|
||||
var cEditor = CodeMirror.fromTextArea(document.getElementById("c-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-csrc"
|
||||
});
|
||||
var cppEditor = CodeMirror.fromTextArea(document.getElementById("cpp-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-c++src"
|
||||
});
|
||||
var javaEditor = CodeMirror.fromTextArea(document.getElementById("java-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-java"
|
||||
});
|
||||
var objectivecEditor = CodeMirror.fromTextArea(document.getElementById("objectivec-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-objectivec"
|
||||
});
|
||||
var scalaEditor = CodeMirror.fromTextArea(document.getElementById("scala-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-scala"
|
||||
});
|
||||
var kotlinEditor = CodeMirror.fromTextArea(document.getElementById("kotlin-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-kotlin"
|
||||
});
|
||||
var ceylonEditor = CodeMirror.fromTextArea(document.getElementById("ceylon-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-ceylon"
|
||||
});
|
||||
var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
|
||||
CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
|
||||
</script>
|
||||
|
||||
<p>Simple mode that tries to handle C-like languages as well as it
|
||||
can. Takes two configuration parameters: <code>keywords</code>, an
|
||||
object whose property names are the keywords in the language,
|
||||
and <code>useCPP</code>, which determines whether C preprocessor
|
||||
directives are recognized.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
|
||||
(C), <code>text/x-c++src</code> (C++), <code>text/x-java</code>
|
||||
(Java), <code>text/x-csharp</code> (C#),
|
||||
<code>text/x-objectivec</code> (Objective-C),
|
||||
<code>text/x-scala</code> (Scala), <code>text/x-vertex</code>
|
||||
<code>x-shader/x-fragment</code> (shader programs),
|
||||
<code>text/x-squirrel</code> (Squirrel) and
|
||||
<code>text/x-ceylon</code> (Ceylon)</p>
|
||||
</article>
|
||||
@@ -0,0 +1,767 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Scala mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<link rel="stylesheet" href="../../theme/ambiance.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="clike.js"></script>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Scala</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Scala mode</h2>
|
||||
<form>
|
||||
<textarea id="code" name="code">
|
||||
|
||||
/* __ *\
|
||||
** ________ ___ / / ___ Scala API **
|
||||
** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
|
||||
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
|
||||
** /____/\___/_/ |_/____/_/ | | **
|
||||
** |/ **
|
||||
\* */
|
||||
|
||||
package scala.collection
|
||||
|
||||
import generic._
|
||||
import mutable.{ Builder, ListBuffer }
|
||||
import annotation.{tailrec, migration, bridge}
|
||||
import annotation.unchecked.{ uncheckedVariance => uV }
|
||||
import parallel.ParIterable
|
||||
|
||||
/** A template trait for traversable collections of type `Traversable[A]`.
|
||||
*
|
||||
* $traversableInfo
|
||||
* @define mutability
|
||||
* @define traversableInfo
|
||||
* This is a base trait of all kinds of $mutability Scala collections. It
|
||||
* implements the behavior common to all collections, in terms of a method
|
||||
* `foreach` with signature:
|
||||
* {{{
|
||||
* def foreach[U](f: Elem => U): Unit
|
||||
* }}}
|
||||
* Collection classes mixing in this trait provide a concrete
|
||||
* `foreach` method which traverses all the
|
||||
* elements contained in the collection, applying a given function to each.
|
||||
* They also need to provide a method `newBuilder`
|
||||
* which creates a builder for collections of the same kind.
|
||||
*
|
||||
* A traversable class might or might not have two properties: strictness
|
||||
* and orderedness. Neither is represented as a type.
|
||||
*
|
||||
* The instances of a strict collection class have all their elements
|
||||
* computed before they can be used as values. By contrast, instances of
|
||||
* a non-strict collection class may defer computation of some of their
|
||||
* elements until after the instance is available as a value.
|
||||
* A typical example of a non-strict collection class is a
|
||||
* <a href="../immutable/Stream.html" target="ContentFrame">
|
||||
* `scala.collection.immutable.Stream`</a>.
|
||||
* A more general class of examples are `TraversableViews`.
|
||||
*
|
||||
* If a collection is an instance of an ordered collection class, traversing
|
||||
* its elements with `foreach` will always visit elements in the
|
||||
* same order, even for different runs of the program. If the class is not
|
||||
* ordered, `foreach` can visit elements in different orders for
|
||||
* different runs (but it will keep the same order in the same run).'
|
||||
*
|
||||
* A typical example of a collection class which is not ordered is a
|
||||
* `HashMap` of objects. The traversal order for hash maps will
|
||||
* depend on the hash codes of its elements, and these hash codes might
|
||||
* differ from one run to the next. By contrast, a `LinkedHashMap`
|
||||
* is ordered because it's `foreach` method visits elements in the
|
||||
* order they were inserted into the `HashMap`.
|
||||
*
|
||||
* @author Martin Odersky
|
||||
* @version 2.8
|
||||
* @since 2.8
|
||||
* @tparam A the element type of the collection
|
||||
* @tparam Repr the type of the actual collection containing the elements.
|
||||
*
|
||||
* @define Coll Traversable
|
||||
* @define coll traversable collection
|
||||
*/
|
||||
trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
|
||||
with FilterMonadic[A, Repr]
|
||||
with TraversableOnce[A]
|
||||
with GenTraversableLike[A, Repr]
|
||||
with Parallelizable[A, ParIterable[A]]
|
||||
{
|
||||
self =>
|
||||
|
||||
import Traversable.breaks._
|
||||
|
||||
/** The type implementing this traversable */
|
||||
protected type Self = Repr
|
||||
|
||||
/** The collection of type $coll underlying this `TraversableLike` object.
|
||||
* By default this is implemented as the `TraversableLike` object itself,
|
||||
* but this can be overridden.
|
||||
*/
|
||||
def repr: Repr = this.asInstanceOf[Repr]
|
||||
|
||||
/** The underlying collection seen as an instance of `$Coll`.
|
||||
* By default this is implemented as the current collection object itself,
|
||||
* but this can be overridden.
|
||||
*/
|
||||
protected[this] def thisCollection: Traversable[A] = this.asInstanceOf[Traversable[A]]
|
||||
|
||||
/** A conversion from collections of type `Repr` to `$Coll` objects.
|
||||
* By default this is implemented as just a cast, but this can be overridden.
|
||||
*/
|
||||
protected[this] def toCollection(repr: Repr): Traversable[A] = repr.asInstanceOf[Traversable[A]]
|
||||
|
||||
/** Creates a new builder for this collection type.
|
||||
*/
|
||||
protected[this] def newBuilder: Builder[A, Repr]
|
||||
|
||||
protected[this] def parCombiner = ParIterable.newCombiner[A]
|
||||
|
||||
/** Applies a function `f` to all elements of this $coll.
|
||||
*
|
||||
* Note: this method underlies the implementation of most other bulk operations.
|
||||
* It's important to implement this method in an efficient way.
|
||||
*
|
||||
*
|
||||
* @param f the function that is applied for its side-effect to every element.
|
||||
* The result of function `f` is discarded.
|
||||
*
|
||||
* @tparam U the type parameter describing the result of function `f`.
|
||||
* This result will always be ignored. Typically `U` is `Unit`,
|
||||
* but this is not necessary.
|
||||
*
|
||||
* @usecase def foreach(f: A => Unit): Unit
|
||||
*/
|
||||
def foreach[U](f: A => U): Unit
|
||||
|
||||
/** Tests whether this $coll is empty.
|
||||
*
|
||||
* @return `true` if the $coll contain no elements, `false` otherwise.
|
||||
*/
|
||||
def isEmpty: Boolean = {
|
||||
var result = true
|
||||
breakable {
|
||||
for (x <- this) {
|
||||
result = false
|
||||
break
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/** Tests whether this $coll is known to have a finite size.
|
||||
* All strict collections are known to have finite size. For a non-strict collection
|
||||
* such as `Stream`, the predicate returns `true` if all elements have been computed.
|
||||
* It returns `false` if the stream is not yet evaluated to the end.
|
||||
*
|
||||
* Note: many collection methods will not work on collections of infinite sizes.
|
||||
*
|
||||
* @return `true` if this collection is known to have finite size, `false` otherwise.
|
||||
*/
|
||||
def hasDefiniteSize = true
|
||||
|
||||
def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.seq.size)
|
||||
b ++= thisCollection
|
||||
b ++= that.seq
|
||||
b.result
|
||||
}
|
||||
|
||||
@bridge
|
||||
def ++[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
|
||||
++(that: GenTraversableOnce[B])(bf)
|
||||
|
||||
/** Concatenates this $coll with the elements of a traversable collection.
|
||||
* It differs from ++ in that the right operand determines the type of the
|
||||
* resulting collection rather than the left one.
|
||||
*
|
||||
* @param that the traversable to append.
|
||||
* @tparam B the element type of the returned collection.
|
||||
* @tparam That $thatinfo
|
||||
* @param bf $bfinfo
|
||||
* @return a new collection of type `That` which contains all elements
|
||||
* of this $coll followed by all elements of `that`.
|
||||
*
|
||||
* @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B]
|
||||
*
|
||||
* @return a new $coll which contains all elements of this $coll
|
||||
* followed by all elements of `that`.
|
||||
*/
|
||||
def ++:[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.size)
|
||||
b ++= that
|
||||
b ++= thisCollection
|
||||
b.result
|
||||
}
|
||||
|
||||
/** This overload exists because: for the implementation of ++: we should reuse
|
||||
* that of ++ because many collections override it with more efficient versions.
|
||||
* Since TraversableOnce has no '++' method, we have to implement that directly,
|
||||
* but Traversable and down can use the overload.
|
||||
*/
|
||||
def ++:[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
|
||||
(that ++ seq)(breakOut)
|
||||
|
||||
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
b.sizeHint(this)
|
||||
for (x <- this) b += f(x)
|
||||
b.result
|
||||
}
|
||||
|
||||
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- this) b ++= f(x).seq
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Selects all elements of this $coll which satisfy a predicate.
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return a new $coll consisting of all elements of this $coll that satisfy the given
|
||||
* predicate `p`. The order of the elements is preserved.
|
||||
*/
|
||||
def filter(p: A => Boolean): Repr = {
|
||||
val b = newBuilder
|
||||
for (x <- this)
|
||||
if (p(x)) b += x
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Selects all elements of this $coll which do not satisfy a predicate.
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return a new $coll consisting of all elements of this $coll that do not satisfy the given
|
||||
* predicate `p`. The order of the elements is preserved.
|
||||
*/
|
||||
def filterNot(p: A => Boolean): Repr = filter(!p(_))
|
||||
|
||||
def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- this) if (pf.isDefinedAt(x)) b += pf(x)
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Builds a new collection by applying an option-valued function to all
|
||||
* elements of this $coll on which the function is defined.
|
||||
*
|
||||
* @param f the option-valued function which filters and maps the $coll.
|
||||
* @tparam B the element type of the returned collection.
|
||||
* @tparam That $thatinfo
|
||||
* @param bf $bfinfo
|
||||
* @return a new collection of type `That` resulting from applying the option-valued function
|
||||
* `f` to each element and collecting all defined results.
|
||||
* The order of the elements is preserved.
|
||||
*
|
||||
* @usecase def filterMap[B](f: A => Option[B]): $Coll[B]
|
||||
*
|
||||
* @param pf the partial function which filters and maps the $coll.
|
||||
* @return a new $coll resulting from applying the given option-valued function
|
||||
* `f` to each element and collecting all defined results.
|
||||
* The order of the elements is preserved.
|
||||
def filterMap[B, That](f: A => Option[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- this)
|
||||
f(x) match {
|
||||
case Some(y) => b += y
|
||||
case _ =>
|
||||
}
|
||||
b.result
|
||||
}
|
||||
*/
|
||||
|
||||
/** Partitions this $coll in two ${coll}s according to a predicate.
|
||||
*
|
||||
* @param p the predicate on which to partition.
|
||||
* @return a pair of ${coll}s: the first $coll consists of all elements that
|
||||
* satisfy the predicate `p` and the second $coll consists of all elements
|
||||
* that don't. The relative order of the elements in the resulting ${coll}s
|
||||
* is the same as in the original $coll.
|
||||
*/
|
||||
def partition(p: A => Boolean): (Repr, Repr) = {
|
||||
val l, r = newBuilder
|
||||
for (x <- this) (if (p(x)) l else r) += x
|
||||
(l.result, r.result)
|
||||
}
|
||||
|
||||
def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
|
||||
val m = mutable.Map.empty[K, Builder[A, Repr]]
|
||||
for (elem <- this) {
|
||||
val key = f(elem)
|
||||
val bldr = m.getOrElseUpdate(key, newBuilder)
|
||||
bldr += elem
|
||||
}
|
||||
val b = immutable.Map.newBuilder[K, Repr]
|
||||
for ((k, v) <- m)
|
||||
b += ((k, v.result))
|
||||
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Tests whether a predicate holds for all elements of this $coll.
|
||||
*
|
||||
* $mayNotTerminateInf
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return `true` if the given predicate `p` holds for all elements
|
||||
* of this $coll, otherwise `false`.
|
||||
*/
|
||||
def forall(p: A => Boolean): Boolean = {
|
||||
var result = true
|
||||
breakable {
|
||||
for (x <- this)
|
||||
if (!p(x)) { result = false; break }
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/** Tests whether a predicate holds for some of the elements of this $coll.
|
||||
*
|
||||
* $mayNotTerminateInf
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return `true` if the given predicate `p` holds for some of the
|
||||
* elements of this $coll, otherwise `false`.
|
||||
*/
|
||||
def exists(p: A => Boolean): Boolean = {
|
||||
var result = false
|
||||
breakable {
|
||||
for (x <- this)
|
||||
if (p(x)) { result = true; break }
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/** Finds the first element of the $coll satisfying a predicate, if any.
|
||||
*
|
||||
* $mayNotTerminateInf
|
||||
* $orderDependent
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return an option value containing the first element in the $coll
|
||||
* that satisfies `p`, or `None` if none exists.
|
||||
*/
|
||||
def find(p: A => Boolean): Option[A] = {
|
||||
var result: Option[A] = None
|
||||
breakable {
|
||||
for (x <- this)
|
||||
if (p(x)) { result = Some(x); break }
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
def scan[B >: A, That](z: B)(op: (B, B) => B)(implicit cbf: CanBuildFrom[Repr, B, That]): That = scanLeft(z)(op)
|
||||
|
||||
def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
b.sizeHint(this, 1)
|
||||
var acc = z
|
||||
b += acc
|
||||
for (x <- this) { acc = op(acc, x); b += acc }
|
||||
b.result
|
||||
}
|
||||
|
||||
@migration(2, 9,
|
||||
"This scanRight definition has changed in 2.9.\n" +
|
||||
"The previous behavior can be reproduced with scanRight.reverse."
|
||||
)
|
||||
def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
var scanned = List(z)
|
||||
var acc = z
|
||||
for (x <- reversed) {
|
||||
acc = op(x, acc)
|
||||
scanned ::= acc
|
||||
}
|
||||
val b = bf(repr)
|
||||
for (elem <- scanned) b += elem
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Selects the first element of this $coll.
|
||||
* $orderDependent
|
||||
* @return the first element of this $coll.
|
||||
* @throws `NoSuchElementException` if the $coll is empty.
|
||||
*/
|
||||
def head: A = {
|
||||
var result: () => A = () => throw new NoSuchElementException
|
||||
breakable {
|
||||
for (x <- this) {
|
||||
result = () => x
|
||||
break
|
||||
}
|
||||
}
|
||||
result()
|
||||
}
|
||||
|
||||
/** Optionally selects the first element.
|
||||
* $orderDependent
|
||||
* @return the first element of this $coll if it is nonempty, `None` if it is empty.
|
||||
*/
|
||||
def headOption: Option[A] = if (isEmpty) None else Some(head)
|
||||
|
||||
/** Selects all elements except the first.
|
||||
* $orderDependent
|
||||
* @return a $coll consisting of all elements of this $coll
|
||||
* except the first one.
|
||||
* @throws `UnsupportedOperationException` if the $coll is empty.
|
||||
*/
|
||||
override def tail: Repr = {
|
||||
if (isEmpty) throw new UnsupportedOperationException("empty.tail")
|
||||
drop(1)
|
||||
}
|
||||
|
||||
/** Selects the last element.
|
||||
* $orderDependent
|
||||
* @return The last element of this $coll.
|
||||
* @throws NoSuchElementException If the $coll is empty.
|
||||
*/
|
||||
def last: A = {
|
||||
var lst = head
|
||||
for (x <- this)
|
||||
lst = x
|
||||
lst
|
||||
}
|
||||
|
||||
/** Optionally selects the last element.
|
||||
* $orderDependent
|
||||
* @return the last element of this $coll$ if it is nonempty, `None` if it is empty.
|
||||
*/
|
||||
def lastOption: Option[A] = if (isEmpty) None else Some(last)
|
||||
|
||||
/** Selects all elements except the last.
|
||||
* $orderDependent
|
||||
* @return a $coll consisting of all elements of this $coll
|
||||
* except the last one.
|
||||
* @throws `UnsupportedOperationException` if the $coll is empty.
|
||||
*/
|
||||
def init: Repr = {
|
||||
if (isEmpty) throw new UnsupportedOperationException("empty.init")
|
||||
var lst = head
|
||||
var follow = false
|
||||
val b = newBuilder
|
||||
b.sizeHint(this, -1)
|
||||
for (x <- this.seq) {
|
||||
if (follow) b += lst
|
||||
else follow = true
|
||||
lst = x
|
||||
}
|
||||
b.result
|
||||
}
|
||||
|
||||
def take(n: Int): Repr = slice(0, n)
|
||||
|
||||
def drop(n: Int): Repr =
|
||||
if (n <= 0) {
|
||||
val b = newBuilder
|
||||
b.sizeHint(this)
|
||||
b ++= thisCollection result
|
||||
}
|
||||
else sliceWithKnownDelta(n, Int.MaxValue, -n)
|
||||
|
||||
def slice(from: Int, until: Int): Repr = sliceWithKnownBound(math.max(from, 0), until)
|
||||
|
||||
// Precondition: from >= 0, until > 0, builder already configured for building.
|
||||
private[this] def sliceInternal(from: Int, until: Int, b: Builder[A, Repr]): Repr = {
|
||||
var i = 0
|
||||
breakable {
|
||||
for (x <- this.seq) {
|
||||
if (i >= from) b += x
|
||||
i += 1
|
||||
if (i >= until) break
|
||||
}
|
||||
}
|
||||
b.result
|
||||
}
|
||||
// Precondition: from >= 0
|
||||
private[scala] def sliceWithKnownDelta(from: Int, until: Int, delta: Int): Repr = {
|
||||
val b = newBuilder
|
||||
if (until <= from) b.result
|
||||
else {
|
||||
b.sizeHint(this, delta)
|
||||
sliceInternal(from, until, b)
|
||||
}
|
||||
}
|
||||
// Precondition: from >= 0
|
||||
private[scala] def sliceWithKnownBound(from: Int, until: Int): Repr = {
|
||||
val b = newBuilder
|
||||
if (until <= from) b.result
|
||||
else {
|
||||
b.sizeHintBounded(until - from, this)
|
||||
sliceInternal(from, until, b)
|
||||
}
|
||||
}
|
||||
|
||||
def takeWhile(p: A => Boolean): Repr = {
|
||||
val b = newBuilder
|
||||
breakable {
|
||||
for (x <- this) {
|
||||
if (!p(x)) break
|
||||
b += x
|
||||
}
|
||||
}
|
||||
b.result
|
||||
}
|
||||
|
||||
def dropWhile(p: A => Boolean): Repr = {
|
||||
val b = newBuilder
|
||||
var go = false
|
||||
for (x <- this) {
|
||||
if (!p(x)) go = true
|
||||
if (go) b += x
|
||||
}
|
||||
b.result
|
||||
}
|
||||
|
||||
def span(p: A => Boolean): (Repr, Repr) = {
|
||||
val l, r = newBuilder
|
||||
var toLeft = true
|
||||
for (x <- this) {
|
||||
toLeft = toLeft && p(x)
|
||||
(if (toLeft) l else r) += x
|
||||
}
|
||||
(l.result, r.result)
|
||||
}
|
||||
|
||||
def splitAt(n: Int): (Repr, Repr) = {
|
||||
val l, r = newBuilder
|
||||
l.sizeHintBounded(n, this)
|
||||
if (n >= 0) r.sizeHint(this, -n)
|
||||
var i = 0
|
||||
for (x <- this) {
|
||||
(if (i < n) l else r) += x
|
||||
i += 1
|
||||
}
|
||||
(l.result, r.result)
|
||||
}
|
||||
|
||||
/** Iterates over the tails of this $coll. The first value will be this
|
||||
* $coll and the final one will be an empty $coll, with the intervening
|
||||
* values the results of successive applications of `tail`.
|
||||
*
|
||||
* @return an iterator over all the tails of this $coll
|
||||
* @example `List(1,2,3).tails = Iterator(List(1,2,3), List(2,3), List(3), Nil)`
|
||||
*/
|
||||
def tails: Iterator[Repr] = iterateUntilEmpty(_.tail)
|
||||
|
||||
/** Iterates over the inits of this $coll. The first value will be this
|
||||
* $coll and the final one will be an empty $coll, with the intervening
|
||||
* values the results of successive applications of `init`.
|
||||
*
|
||||
* @return an iterator over all the inits of this $coll
|
||||
* @example `List(1,2,3).inits = Iterator(List(1,2,3), List(1,2), List(1), Nil)`
|
||||
*/
|
||||
def inits: Iterator[Repr] = iterateUntilEmpty(_.init)
|
||||
|
||||
/** Copies elements of this $coll to an array.
|
||||
* Fills the given array `xs` with at most `len` elements of
|
||||
* this $coll, starting at position `start`.
|
||||
* Copying will stop once either the end of the current $coll is reached,
|
||||
* or the end of the array is reached, or `len` elements have been copied.
|
||||
*
|
||||
* $willNotTerminateInf
|
||||
*
|
||||
* @param xs the array to fill.
|
||||
* @param start the starting index.
|
||||
* @param len the maximal number of elements to copy.
|
||||
* @tparam B the type of the elements of the array.
|
||||
*
|
||||
*
|
||||
* @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit
|
||||
*/
|
||||
def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
|
||||
var i = start
|
||||
val end = (start + len) min xs.length
|
||||
breakable {
|
||||
for (x <- this) {
|
||||
if (i >= end) break
|
||||
xs(i) = x
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def toTraversable: Traversable[A] = thisCollection
|
||||
def toIterator: Iterator[A] = toStream.iterator
|
||||
def toStream: Stream[A] = toBuffer.toStream
|
||||
|
||||
/** Converts this $coll to a string.
|
||||
*
|
||||
* @return a string representation of this collection. By default this
|
||||
* string consists of the `stringPrefix` of this $coll,
|
||||
* followed by all elements separated by commas and enclosed in parentheses.
|
||||
*/
|
||||
override def toString = mkString(stringPrefix + "(", ", ", ")")
|
||||
|
||||
/** Defines the prefix of this object's `toString` representation.
|
||||
*
|
||||
* @return a string representation which starts the result of `toString`
|
||||
* applied to this $coll. By default the string prefix is the
|
||||
* simple name of the collection class $coll.
|
||||
*/
|
||||
def stringPrefix : String = {
|
||||
var string = repr.asInstanceOf[AnyRef].getClass.getName
|
||||
val idx1 = string.lastIndexOf('.' : Int)
|
||||
if (idx1 != -1) string = string.substring(idx1 + 1)
|
||||
val idx2 = string.indexOf('$')
|
||||
if (idx2 != -1) string = string.substring(0, idx2)
|
||||
string
|
||||
}
|
||||
|
||||
/** Creates a non-strict view of this $coll.
|
||||
*
|
||||
* @return a non-strict view of this $coll.
|
||||
*/
|
||||
def view = new TraversableView[A, Repr] {
|
||||
protected lazy val underlying = self.repr
|
||||
override def foreach[U](f: A => U) = self foreach f
|
||||
}
|
||||
|
||||
/** Creates a non-strict view of a slice of this $coll.
|
||||
*
|
||||
* Note: the difference between `view` and `slice` is that `view` produces
|
||||
* a view of the current $coll, whereas `slice` produces a new $coll.
|
||||
*
|
||||
* Note: `view(from, to)` is equivalent to `view.slice(from, to)`
|
||||
* $orderDependent
|
||||
*
|
||||
* @param from the index of the first element of the view
|
||||
* @param until the index of the element following the view
|
||||
* @return a non-strict view of a slice of this $coll, starting at index `from`
|
||||
* and extending up to (but not including) index `until`.
|
||||
*/
|
||||
def view(from: Int, until: Int): TraversableView[A, Repr] = view.slice(from, until)
|
||||
|
||||
/** Creates a non-strict filter of this $coll.
|
||||
*
|
||||
* Note: the difference between `c filter p` and `c withFilter p` is that
|
||||
* the former creates a new collection, whereas the latter only
|
||||
* restricts the domain of subsequent `map`, `flatMap`, `foreach`,
|
||||
* and `withFilter` operations.
|
||||
* $orderDependent
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return an object of class `WithFilter`, which supports
|
||||
* `map`, `flatMap`, `foreach`, and `withFilter` operations.
|
||||
* All these operations apply to those elements of this $coll which
|
||||
* satisfy the predicate `p`.
|
||||
*/
|
||||
def withFilter(p: A => Boolean): FilterMonadic[A, Repr] = new WithFilter(p)
|
||||
|
||||
/** A class supporting filtered operations. Instances of this class are
|
||||
* returned by method `withFilter`.
|
||||
*/
|
||||
class WithFilter(p: A => Boolean) extends FilterMonadic[A, Repr] {
|
||||
|
||||
/** Builds a new collection by applying a function to all elements of the
|
||||
* outer $coll containing this `WithFilter` instance that satisfy predicate `p`.
|
||||
*
|
||||
* @param f the function to apply to each element.
|
||||
* @tparam B the element type of the returned collection.
|
||||
* @tparam That $thatinfo
|
||||
* @param bf $bfinfo
|
||||
* @return a new collection of type `That` resulting from applying
|
||||
* the given function `f` to each element of the outer $coll
|
||||
* that satisfies predicate `p` and collecting the results.
|
||||
*
|
||||
* @usecase def map[B](f: A => B): $Coll[B]
|
||||
*
|
||||
* @return a new $coll resulting from applying the given function
|
||||
* `f` to each element of the outer $coll that satisfies
|
||||
* predicate `p` and collecting the results.
|
||||
*/
|
||||
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- self)
|
||||
if (p(x)) b += f(x)
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Builds a new collection by applying a function to all elements of the
|
||||
* outer $coll containing this `WithFilter` instance that satisfy
|
||||
* predicate `p` and concatenating the results.
|
||||
*
|
||||
* @param f the function to apply to each element.
|
||||
* @tparam B the element type of the returned collection.
|
||||
* @tparam That $thatinfo
|
||||
* @param bf $bfinfo
|
||||
* @return a new collection of type `That` resulting from applying
|
||||
* the given collection-valued function `f` to each element
|
||||
* of the outer $coll that satisfies predicate `p` and
|
||||
* concatenating the results.
|
||||
*
|
||||
* @usecase def flatMap[B](f: A => TraversableOnce[B]): $Coll[B]
|
||||
*
|
||||
* @return a new $coll resulting from applying the given collection-valued function
|
||||
* `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
|
||||
*/
|
||||
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- self)
|
||||
if (p(x)) b ++= f(x).seq
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Applies a function `f` to all elements of the outer $coll containing
|
||||
* this `WithFilter` instance that satisfy predicate `p`.
|
||||
*
|
||||
* @param f the function that is applied for its side-effect to every element.
|
||||
* The result of function `f` is discarded.
|
||||
*
|
||||
* @tparam U the type parameter describing the result of function `f`.
|
||||
* This result will always be ignored. Typically `U` is `Unit`,
|
||||
* but this is not necessary.
|
||||
*
|
||||
* @usecase def foreach(f: A => Unit): Unit
|
||||
*/
|
||||
def foreach[U](f: A => U): Unit =
|
||||
for (x <- self)
|
||||
if (p(x)) f(x)
|
||||
|
||||
/** Further refines the filter for this $coll.
|
||||
*
|
||||
* @param q the predicate used to test elements.
|
||||
* @return an object of class `WithFilter`, which supports
|
||||
* `map`, `flatMap`, `foreach`, and `withFilter` operations.
|
||||
* All these operations apply to those elements of this $coll which
|
||||
* satisfy the predicate `q` in addition to the predicate `p`.
|
||||
*/
|
||||
def withFilter(q: A => Boolean): WithFilter =
|
||||
new WithFilter(x => p(x) && q(x))
|
||||
}
|
||||
|
||||
// A helper for tails and inits.
|
||||
private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {
|
||||
val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)
|
||||
it ++ Iterator(Nil) map (newBuilder ++= _ result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</textarea>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
theme: "ambiance",
|
||||
mode: "text/x-scala"
|
||||
});
|
||||
</script>
|
||||
</article>
|
||||
@@ -0,0 +1,55 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-c");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
MT("indent",
|
||||
"[variable-3 void] [def foo]([variable-3 void*] [variable a], [variable-3 int] [variable b]) {",
|
||||
" [variable-3 int] [variable c] [operator =] [variable b] [operator +]",
|
||||
" [number 1];",
|
||||
" [keyword return] [operator *][variable a];",
|
||||
"}");
|
||||
|
||||
MT("indent_switch",
|
||||
"[keyword switch] ([variable x]) {",
|
||||
" [keyword case] [number 10]:",
|
||||
" [keyword return] [number 20];",
|
||||
" [keyword default]:",
|
||||
" [variable printf]([string \"foo %c\"], [variable x]);",
|
||||
"}");
|
||||
|
||||
MT("def",
|
||||
"[variable-3 void] [def foo]() {}",
|
||||
"[keyword struct] [def bar]{}",
|
||||
"[variable-3 int] [variable-3 *][def baz]() {}");
|
||||
|
||||
MT("def_new_line",
|
||||
"::[variable std]::[variable SomeTerribleType][operator <][variable T][operator >]",
|
||||
"[def SomeLongMethodNameThatDoesntFitIntoOneLine]([keyword const] [variable MyType][operator &] [variable param]) {}")
|
||||
|
||||
MT("double_block",
|
||||
"[keyword for] (;;)",
|
||||
" [keyword for] (;;)",
|
||||
" [variable x][operator ++];",
|
||||
"[keyword return];");
|
||||
|
||||
MT("preprocessor",
|
||||
"[meta #define FOO 3]",
|
||||
"[variable-3 int] [variable foo];",
|
||||
"[meta #define BAR\\]",
|
||||
"[meta 4]",
|
||||
"[variable-3 unsigned] [variable-3 int] [variable bar] [operator =] [number 8];",
|
||||
"[meta #include <baz> ][comment // comment]")
|
||||
|
||||
|
||||
var mode_cpp = CodeMirror.getMode({indentUnit: 2}, "text/x-c++src");
|
||||
function MTCPP(name) { test.mode(name, mode_cpp, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
MTCPP("cpp14_literal",
|
||||
"[number 10'000];",
|
||||
"[number 0b10'000];",
|
||||
"[number 0x10'000];",
|
||||
"[string '100000'];");
|
||||
})();
|
||||
@@ -0,0 +1,306 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/**
|
||||
* Author: Hans Engel
|
||||
* Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)
|
||||
*/
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("clojure", function (options) {
|
||||
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2",
|
||||
ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable";
|
||||
var INDENT_WORD_SKIP = options.indentUnit || 2;
|
||||
var NORMAL_INDENT_UNIT = options.indentUnit || 2;
|
||||
|
||||
function makeKeywords(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
var atoms = makeKeywords("true false nil");
|
||||
|
||||
var keywords = makeKeywords(
|
||||
"defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest " +
|
||||
"slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn " +
|
||||
"do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync " +
|
||||
"doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars " +
|
||||
"binding gen-class gen-and-load-class gen-and-save-class handler-case handle");
|
||||
|
||||
var builtins = makeKeywords(
|
||||
"* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* " +
|
||||
"*compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* " +
|
||||
"*math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* " +
|
||||
"*source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> " +
|
||||
"->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor " +
|
||||
"aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! " +
|
||||
"alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double " +
|
||||
"aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 " +
|
||||
"bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set " +
|
||||
"bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast " +
|
||||
"byte byte-array bytes case cat cast char char-array char-escape-string char-name-string char? chars chunk chunk-append " +
|
||||
"chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors " +
|
||||
"clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement completing concat cond condp " +
|
||||
"conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? " +
|
||||
"declare dedupe default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol " +
|
||||
"defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc " +
|
||||
"dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last " +
|
||||
"drop-while eduction empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info " +
|
||||
"extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword " +
|
||||
"find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? " +
|
||||
"fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? " +
|
||||
"gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash " +
|
||||
"hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? " +
|
||||
"int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep " +
|
||||
"keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file " +
|
||||
"load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array " +
|
||||
"make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods " +
|
||||
"min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty " +
|
||||
"not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias " +
|
||||
"ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all " +
|
||||
"partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers " +
|
||||
"primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str " +
|
||||
"prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues " +
|
||||
"quot rand rand-int rand-nth random-sample range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern " +
|
||||
"re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history " +
|
||||
"ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods " +
|
||||
"remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest " +
|
||||
"restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? " +
|
||||
"seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts " +
|
||||
"shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? " +
|
||||
"special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol " +
|
||||
"symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transduce " +
|
||||
"transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec " +
|
||||
"unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int " +
|
||||
"unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int "+
|
||||
"unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote " +
|
||||
"unquote-splicing update update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of " +
|
||||
"vector? volatile! volatile? vreset! vswap! when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context " +
|
||||
"with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap " +
|
||||
"*default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! " +
|
||||
"set-agent-send-off-executor! some-> some->>");
|
||||
|
||||
var indentKeys = makeKeywords(
|
||||
// Built-ins
|
||||
"ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto " +
|
||||
"locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type " +
|
||||
"try catch " +
|
||||
|
||||
// Binding forms
|
||||
"let letfn binding loop for doseq dotimes when-let if-let " +
|
||||
|
||||
// Data structures
|
||||
"defstruct struct-map assoc " +
|
||||
|
||||
// clojure.test
|
||||
"testing deftest " +
|
||||
|
||||
// contrib
|
||||
"handler-case handle dotrace deftrace");
|
||||
|
||||
var tests = {
|
||||
digit: /\d/,
|
||||
digit_or_colon: /[\d:]/,
|
||||
hex: /[0-9a-f]/i,
|
||||
sign: /[+-]/,
|
||||
exponent: /e/i,
|
||||
keyword_char: /[^\s\(\[\;\)\]]/,
|
||||
symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/,
|
||||
block_indent: /^(?:def|with)[^\/]+$|\/(?:def|with)/
|
||||
};
|
||||
|
||||
function stateStack(indent, type, prev) { // represents a state stack object
|
||||
this.indent = indent;
|
||||
this.type = type;
|
||||
this.prev = prev;
|
||||
}
|
||||
|
||||
function pushStack(state, indent, type) {
|
||||
state.indentStack = new stateStack(indent, type, state.indentStack);
|
||||
}
|
||||
|
||||
function popStack(state) {
|
||||
state.indentStack = state.indentStack.prev;
|
||||
}
|
||||
|
||||
function isNumber(ch, stream){
|
||||
// hex
|
||||
if ( ch === '0' && stream.eat(/x/i) ) {
|
||||
stream.eatWhile(tests.hex);
|
||||
return true;
|
||||
}
|
||||
|
||||
// leading sign
|
||||
if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
|
||||
stream.eat(tests.sign);
|
||||
ch = stream.next();
|
||||
}
|
||||
|
||||
if ( tests.digit.test(ch) ) {
|
||||
stream.eat(ch);
|
||||
stream.eatWhile(tests.digit);
|
||||
|
||||
if ( '.' == stream.peek() ) {
|
||||
stream.eat('.');
|
||||
stream.eatWhile(tests.digit);
|
||||
} else if ('/' == stream.peek() ) {
|
||||
stream.eat('/');
|
||||
stream.eatWhile(tests.digit);
|
||||
}
|
||||
|
||||
if ( stream.eat(tests.exponent) ) {
|
||||
stream.eat(tests.sign);
|
||||
stream.eatWhile(tests.digit);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Eat character that starts after backslash \
|
||||
function eatCharacter(stream) {
|
||||
var first = stream.next();
|
||||
// Read special literals: backspace, newline, space, return.
|
||||
// Just read all lowercase letters.
|
||||
if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {
|
||||
return;
|
||||
}
|
||||
// Read unicode character: \u1000 \uA0a1
|
||||
if (first === "u") {
|
||||
stream.match(/[0-9a-z]{4}/i, true);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function () {
|
||||
return {
|
||||
indentStack: null,
|
||||
indentation: 0,
|
||||
mode: false
|
||||
};
|
||||
},
|
||||
|
||||
token: function (stream, state) {
|
||||
if (state.indentStack == null && stream.sol()) {
|
||||
// update indentation, but only if indentStack is empty
|
||||
state.indentation = stream.indentation();
|
||||
}
|
||||
|
||||
// skip spaces
|
||||
if (state.mode != "string" && stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
var returnType = null;
|
||||
|
||||
switch(state.mode){
|
||||
case "string": // multi-line string parsing mode
|
||||
var next, escaped = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == "\"" && !escaped) {
|
||||
|
||||
state.mode = false;
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
returnType = STRING; // continue on in string mode
|
||||
break;
|
||||
default: // default parsing mode
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch == "\"") {
|
||||
state.mode = "string";
|
||||
returnType = STRING;
|
||||
} else if (ch == "\\") {
|
||||
eatCharacter(stream);
|
||||
returnType = CHARACTER;
|
||||
} else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
|
||||
returnType = ATOM;
|
||||
} else if (ch == ";") { // comment
|
||||
stream.skipToEnd(); // rest of the line is a comment
|
||||
returnType = COMMENT;
|
||||
} else if (isNumber(ch,stream)){
|
||||
returnType = NUMBER;
|
||||
} else if (ch == "(" || ch == "[" || ch == "{" ) {
|
||||
var keyWord = '', indentTemp = stream.column(), letter;
|
||||
/**
|
||||
Either
|
||||
(indent-word ..
|
||||
(non-indent-word ..
|
||||
(;something else, bracket, etc.
|
||||
*/
|
||||
|
||||
if (ch == "(") while ((letter = stream.eat(tests.keyword_char)) != null) {
|
||||
keyWord += letter;
|
||||
}
|
||||
|
||||
if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) ||
|
||||
tests.block_indent.test(keyWord))) { // indent-word
|
||||
pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
|
||||
} else { // non-indent word
|
||||
// we continue eating the spaces
|
||||
stream.eatSpace();
|
||||
if (stream.eol() || stream.peek() == ";") {
|
||||
// nothing significant after
|
||||
// we restart indentation the user defined spaces after
|
||||
pushStack(state, indentTemp + NORMAL_INDENT_UNIT, ch);
|
||||
} else {
|
||||
pushStack(state, indentTemp + stream.current().length, ch); // else we match
|
||||
}
|
||||
}
|
||||
stream.backUp(stream.current().length - 1); // undo all the eating
|
||||
|
||||
returnType = BRACKET;
|
||||
} else if (ch == ")" || ch == "]" || ch == "}") {
|
||||
returnType = BRACKET;
|
||||
if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : (ch == "]" ? "[" :"{"))) {
|
||||
popStack(state);
|
||||
}
|
||||
} else if ( ch == ":" ) {
|
||||
stream.eatWhile(tests.symbol);
|
||||
return ATOM;
|
||||
} else {
|
||||
stream.eatWhile(tests.symbol);
|
||||
|
||||
if (keywords && keywords.propertyIsEnumerable(stream.current())) {
|
||||
returnType = KEYWORD;
|
||||
} else if (builtins && builtins.propertyIsEnumerable(stream.current())) {
|
||||
returnType = BUILTIN;
|
||||
} else if (atoms && atoms.propertyIsEnumerable(stream.current())) {
|
||||
returnType = ATOM;
|
||||
} else {
|
||||
returnType = VAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnType;
|
||||
},
|
||||
|
||||
indent: function (state) {
|
||||
if (state.indentStack == null) return state.indentation;
|
||||
return state.indentStack.indent;
|
||||
},
|
||||
|
||||
closeBrackets: {pairs: "()[]{}\"\""},
|
||||
lineComment: ";;"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-clojure", "clojure");
|
||||
CodeMirror.defineMIME("text/x-clojurescript", "clojure");
|
||||
CodeMirror.defineMIME("application/edn", "clojure");
|
||||
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Clojure mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="clojure.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Clojure</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Clojure mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
; Conway's Game of Life, based on the work of:
|
||||
;; Laurent Petit https://gist.github.com/1200343
|
||||
;; Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life
|
||||
|
||||
(ns ^{:doc "Conway's Game of Life."}
|
||||
game-of-life)
|
||||
|
||||
;; Core game of life's algorithm functions
|
||||
|
||||
(defn neighbours
|
||||
"Given a cell's coordinates, returns the coordinates of its neighbours."
|
||||
[[x y]]
|
||||
(for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]
|
||||
[(+ dx x) (+ dy y)]))
|
||||
|
||||
(defn step
|
||||
"Given a set of living cells, computes the new set of living cells."
|
||||
[cells]
|
||||
(set (for [[cell n] (frequencies (mapcat neighbours cells))
|
||||
:when (or (= n 3) (and (= n 2) (cells cell)))]
|
||||
cell)))
|
||||
|
||||
;; Utility methods for displaying game on a text terminal
|
||||
|
||||
(defn print-board
|
||||
"Prints a board on *out*, representing a step in the game."
|
||||
[board w h]
|
||||
(doseq [x (range (inc w)) y (range (inc h))]
|
||||
(if (= y 0) (print "\n"))
|
||||
(print (if (board [x y]) "[X]" " . "))))
|
||||
|
||||
(defn display-grids
|
||||
"Prints a squence of boards on *out*, representing several steps."
|
||||
[grids w h]
|
||||
(doseq [board grids]
|
||||
(print-board board w h)
|
||||
(print "\n")))
|
||||
|
||||
;; Launches an example board
|
||||
|
||||
(def
|
||||
^{:doc "board represents the initial set of living cells"}
|
||||
board #{[2 1] [2 2] [2 3]})
|
||||
|
||||
(display-grids (take 3 (iterate step board)) 5 5)
|
||||
|
||||
;; Let's play with characters
|
||||
(println \1 \a \# \\
|
||||
\" \( \newline
|
||||
\} \" \space
|
||||
\tab \return \backspace
|
||||
\u1000 \uAaAa \u9F9F)
|
||||
|
||||
;; Let's play with numbers
|
||||
(+ 1 -1 1/2 -1/2 -0.5 0.5)
|
||||
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-clojure</code>.</p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,97 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object")
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd)
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("cmake", function () {
|
||||
var variable_regex = /({)?[a-zA-Z0-9_]+(})?/;
|
||||
|
||||
function tokenString(stream, state) {
|
||||
var current, prev, found_var = false;
|
||||
while (!stream.eol() && (current = stream.next()) != state.pending) {
|
||||
if (current === '$' && prev != '\\' && state.pending == '"') {
|
||||
found_var = true;
|
||||
break;
|
||||
}
|
||||
prev = current;
|
||||
}
|
||||
if (found_var) {
|
||||
stream.backUp(1);
|
||||
}
|
||||
if (current == state.pending) {
|
||||
state.continueString = false;
|
||||
} else {
|
||||
state.continueString = true;
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
function tokenize(stream, state) {
|
||||
var ch = stream.next();
|
||||
|
||||
// Have we found a variable?
|
||||
if (ch === '$') {
|
||||
if (stream.match(variable_regex)) {
|
||||
return 'variable-2';
|
||||
}
|
||||
return 'variable';
|
||||
}
|
||||
// Should we still be looking for the end of a string?
|
||||
if (state.continueString) {
|
||||
// If so, go through the loop again
|
||||
stream.backUp(1);
|
||||
return tokenString(stream, state);
|
||||
}
|
||||
// Do we just have a function on our hands?
|
||||
// In 'cmake_minimum_required (VERSION 2.8.8)', 'cmake_minimum_required' is matched
|
||||
if (stream.match(/(\s+)?\w+\(/) || stream.match(/(\s+)?\w+\ \(/)) {
|
||||
stream.backUp(1);
|
||||
return 'def';
|
||||
}
|
||||
if (ch == "#") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
// Have we found a string?
|
||||
if (ch == "'" || ch == '"') {
|
||||
// Store the type (single or double)
|
||||
state.pending = ch;
|
||||
// Perform the looping function to find the end
|
||||
return tokenString(stream, state);
|
||||
}
|
||||
if (ch == '(' || ch == ')') {
|
||||
return 'bracket';
|
||||
}
|
||||
if (ch.match(/[0-9]/)) {
|
||||
return 'number';
|
||||
}
|
||||
stream.eatWhile(/[\w-]/);
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
startState: function () {
|
||||
var state = {};
|
||||
state.inDefinition = false;
|
||||
state.inInclude = false;
|
||||
state.continueString = false;
|
||||
state.pending = false;
|
||||
return state;
|
||||
},
|
||||
token: function (stream, state) {
|
||||
if (stream.eatSpace()) return null;
|
||||
return tokenize(stream, state);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-cmake", "cmake");
|
||||
|
||||
});
|
||||
@@ -0,0 +1,129 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: CMake mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="cmake.js"></script>
|
||||
<style>
|
||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
||||
.cm-s-default span.cm-arrow { color: red; }
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">CMake</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>CMake mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
# vim: syntax=cmake
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
# default to Release build for GCC builds
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
||||
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
endif()
|
||||
message(STATUS "cmake version ${CMAKE_VERSION}")
|
||||
if(POLICY CMP0025)
|
||||
cmake_policy(SET CMP0025 OLD) # report Apple's Clang as just Clang
|
||||
endif()
|
||||
if(POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW) # MACOSX_RPATH
|
||||
endif()
|
||||
|
||||
project (x265)
|
||||
cmake_minimum_required (VERSION 2.8.8) # OBJECT libraries require 2.8.8
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
# X265_BUILD must be incremented each time the public API is changed
|
||||
set(X265_BUILD 48)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
|
||||
"${PROJECT_BINARY_DIR}/x265.def")
|
||||
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
|
||||
"${PROJECT_BINARY_DIR}/x265_config.h")
|
||||
|
||||
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}")
|
||||
|
||||
# System architecture detection
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" SYSPROC)
|
||||
set(X86_ALIASES x86 i386 i686 x86_64 amd64)
|
||||
list(FIND X86_ALIASES "${SYSPROC}" X86MATCH)
|
||||
if("${SYSPROC}" STREQUAL "" OR X86MATCH GREATER "-1")
|
||||
message(STATUS "Detected x86 target processor")
|
||||
set(X86 1)
|
||||
add_definitions(-DX265_ARCH_X86=1)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" MATCHES 8)
|
||||
set(X64 1)
|
||||
add_definitions(-DX86_64=1)
|
||||
endif()
|
||||
elseif(${SYSPROC} STREQUAL "armv6l")
|
||||
message(STATUS "Detected ARM target processor")
|
||||
set(ARM 1)
|
||||
add_definitions(-DX265_ARCH_ARM=1 -DHAVE_ARMV6=1)
|
||||
else()
|
||||
message(STATUS "CMAKE_SYSTEM_PROCESSOR value `${CMAKE_SYSTEM_PROCESSOR}` is unknown")
|
||||
message(STATUS "Please add this value near ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE}")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
list(APPEND PLATFORM_LIBS pthread)
|
||||
find_library(LIBRT rt)
|
||||
if(LIBRT)
|
||||
list(APPEND PLATFORM_LIBS rt)
|
||||
endif()
|
||||
find_package(Numa)
|
||||
if(NUMA_FOUND)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${NUMA_LIBRARY})
|
||||
check_symbol_exists(numa_node_of_cpu numa.h NUMA_V2)
|
||||
if(NUMA_V2)
|
||||
add_definitions(-DHAVE_LIBNUMA)
|
||||
message(STATUS "libnuma found, building with support for NUMA nodes")
|
||||
list(APPEND PLATFORM_LIBS ${NUMA_LIBRARY})
|
||||
link_directories(${NUMA_LIBRARY_DIR})
|
||||
include_directories(${NUMA_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
mark_as_advanced(LIBRT NUMA_FOUND)
|
||||
endif(UNIX)
|
||||
|
||||
if(X64 AND NOT WIN32)
|
||||
option(ENABLE_PIC "Enable Position Independent Code" ON)
|
||||
else()
|
||||
option(ENABLE_PIC "Enable Position Independent Code" OFF)
|
||||
endif(X64 AND NOT WIN32)
|
||||
|
||||
# Compiler detection
|
||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(XCODE 1)
|
||||
endif()
|
||||
if (APPLE)
|
||||
add_definitions(-DMACOS)
|
||||
endif()
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: "text/x-cmake",
|
||||
matchBrackets: true,
|
||||
indentUnit: 4
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-cmake</code>.</p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,255 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/**
|
||||
* Author: Gautam Mehta
|
||||
* Branched from CodeMirror's Scheme mode
|
||||
*/
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("cobol", function () {
|
||||
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
|
||||
ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header",
|
||||
COBOLLINENUM = "def", PERIOD = "link";
|
||||
function makeKeywords(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES ");
|
||||
var keywords = makeKeywords(
|
||||
"ACCEPT ACCESS ACQUIRE ADD ADDRESS " +
|
||||
"ADVANCING AFTER ALIAS ALL ALPHABET " +
|
||||
"ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " +
|
||||
"ALSO ALTER ALTERNATE AND ANY " +
|
||||
"ARE AREA AREAS ARITHMETIC ASCENDING " +
|
||||
"ASSIGN AT ATTRIBUTE AUTHOR AUTO " +
|
||||
"AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " +
|
||||
"B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " +
|
||||
"BEFORE BELL BINARY BIT BITS " +
|
||||
"BLANK BLINK BLOCK BOOLEAN BOTTOM " +
|
||||
"BY CALL CANCEL CD CF " +
|
||||
"CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " +
|
||||
"CLOSE COBOL CODE CODE-SET COL " +
|
||||
"COLLATING COLUMN COMMA COMMIT COMMITMENT " +
|
||||
"COMMON COMMUNICATION COMP COMP-0 COMP-1 " +
|
||||
"COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " +
|
||||
"COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " +
|
||||
"COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " +
|
||||
"COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " +
|
||||
"CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " +
|
||||
"CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " +
|
||||
"CONVERTING COPY CORR CORRESPONDING COUNT " +
|
||||
"CRT CRT-UNDER CURRENCY CURRENT CURSOR " +
|
||||
"DATA DATE DATE-COMPILED DATE-WRITTEN DAY " +
|
||||
"DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " +
|
||||
"DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " +
|
||||
"DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " +
|
||||
"DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " +
|
||||
"DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " +
|
||||
"DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " +
|
||||
"DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " +
|
||||
"DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " +
|
||||
"DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " +
|
||||
"DOWN DROP DUPLICATE DUPLICATES DYNAMIC " +
|
||||
"EBCDIC EGI EJECT ELSE EMI " +
|
||||
"EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " +
|
||||
"END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " +
|
||||
"END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " +
|
||||
"END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " +
|
||||
"END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " +
|
||||
"END-UNSTRING END-WRITE END-XML ENTER ENTRY " +
|
||||
"ENVIRONMENT EOP EQUAL EQUALS ERASE " +
|
||||
"ERROR ESI EVALUATE EVERY EXCEEDS " +
|
||||
"EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " +
|
||||
"EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " +
|
||||
"FILE-STREAM FILES FILLER FINAL FIND " +
|
||||
"FINISH FIRST FOOTING FOR FOREGROUND-COLOR " +
|
||||
"FOREGROUND-COLOUR FORMAT FREE FROM FULL " +
|
||||
"FUNCTION GENERATE GET GIVING GLOBAL " +
|
||||
"GO GOBACK GREATER GROUP HEADING " +
|
||||
"HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " +
|
||||
"ID IDENTIFICATION IF IN INDEX " +
|
||||
"INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " +
|
||||
"INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " +
|
||||
"INDIC INDICATE INDICATOR INDICATORS INITIAL " +
|
||||
"INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " +
|
||||
"INSTALLATION INTO INVALID INVOKE IS " +
|
||||
"JUST JUSTIFIED KANJI KEEP KEY " +
|
||||
"LABEL LAST LD LEADING LEFT " +
|
||||
"LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " +
|
||||
"LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " +
|
||||
"LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " +
|
||||
"LOCALE LOCALLY LOCK " +
|
||||
"MEMBER MEMORY MERGE MESSAGE METACLASS " +
|
||||
"MODE MODIFIED MODIFY MODULES MOVE " +
|
||||
"MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " +
|
||||
"NEXT NO NO-ECHO NONE NOT " +
|
||||
"NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " +
|
||||
"NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " +
|
||||
"OF OFF OMITTED ON ONLY " +
|
||||
"OPEN OPTIONAL OR ORDER ORGANIZATION " +
|
||||
"OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " +
|
||||
"PADDING PAGE PAGE-COUNTER PARSE PERFORM " +
|
||||
"PF PH PIC PICTURE PLUS " +
|
||||
"POINTER POSITION POSITIVE PREFIX PRESENT " +
|
||||
"PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " +
|
||||
"PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " +
|
||||
"PROMPT PROTECTED PURGE QUEUE QUOTE " +
|
||||
"QUOTES RANDOM RD READ READY " +
|
||||
"REALM RECEIVE RECONNECT RECORD RECORD-NAME " +
|
||||
"RECORDS RECURSIVE REDEFINES REEL REFERENCE " +
|
||||
"REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " +
|
||||
"REMAINDER REMOVAL RENAMES REPEATED REPLACE " +
|
||||
"REPLACING REPORT REPORTING REPORTS REPOSITORY " +
|
||||
"REQUIRED RERUN RESERVE RESET RETAINING " +
|
||||
"RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " +
|
||||
"REVERSED REWIND REWRITE RF RH " +
|
||||
"RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " +
|
||||
"RUN SAME SCREEN SD SEARCH " +
|
||||
"SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " +
|
||||
"SELECT SEND SENTENCE SEPARATE SEQUENCE " +
|
||||
"SEQUENTIAL SET SHARED SIGN SIZE " +
|
||||
"SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " +
|
||||
"SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " +
|
||||
"SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " +
|
||||
"START STARTING STATUS STOP STORE " +
|
||||
"STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " +
|
||||
"SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " +
|
||||
"SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " +
|
||||
"TABLE TALLYING TAPE TENANT TERMINAL " +
|
||||
"TERMINATE TEST TEXT THAN THEN " +
|
||||
"THROUGH THRU TIME TIMES TITLE " +
|
||||
"TO TOP TRAILING TRAILING-SIGN TRANSACTION " +
|
||||
"TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " +
|
||||
"UNSTRING UNTIL UP UPDATE UPON " +
|
||||
"USAGE USAGE-MODE USE USING VALID " +
|
||||
"VALIDATE VALUE VALUES VARYING VLR " +
|
||||
"WAIT WHEN WHEN-COMPILED WITH WITHIN " +
|
||||
"WORDS WORKING-STORAGE WRITE XML XML-CODE " +
|
||||
"XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " );
|
||||
|
||||
var builtins = makeKeywords("- * ** / + < <= = > >= ");
|
||||
var tests = {
|
||||
digit: /\d/,
|
||||
digit_or_colon: /[\d:]/,
|
||||
hex: /[0-9a-f]/i,
|
||||
sign: /[+-]/,
|
||||
exponent: /e/i,
|
||||
keyword_char: /[^\s\(\[\;\)\]]/,
|
||||
symbol: /[\w*+\-]/
|
||||
};
|
||||
function isNumber(ch, stream){
|
||||
// hex
|
||||
if ( ch === '0' && stream.eat(/x/i) ) {
|
||||
stream.eatWhile(tests.hex);
|
||||
return true;
|
||||
}
|
||||
// leading sign
|
||||
if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
|
||||
stream.eat(tests.sign);
|
||||
ch = stream.next();
|
||||
}
|
||||
if ( tests.digit.test(ch) ) {
|
||||
stream.eat(ch);
|
||||
stream.eatWhile(tests.digit);
|
||||
if ( '.' == stream.peek()) {
|
||||
stream.eat('.');
|
||||
stream.eatWhile(tests.digit);
|
||||
}
|
||||
if ( stream.eat(tests.exponent) ) {
|
||||
stream.eat(tests.sign);
|
||||
stream.eatWhile(tests.digit);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
startState: function () {
|
||||
return {
|
||||
indentStack: null,
|
||||
indentation: 0,
|
||||
mode: false
|
||||
};
|
||||
},
|
||||
token: function (stream, state) {
|
||||
if (state.indentStack == null && stream.sol()) {
|
||||
// update indentation, but only if indentStack is empty
|
||||
state.indentation = 6 ; //stream.indentation();
|
||||
}
|
||||
// skip spaces
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
var returnType = null;
|
||||
switch(state.mode){
|
||||
case "string": // multi-line string parsing mode
|
||||
var next = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == "\"" || next == "\'") {
|
||||
state.mode = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
returnType = STRING; // continue on in string mode
|
||||
break;
|
||||
default: // default parsing mode
|
||||
var ch = stream.next();
|
||||
var col = stream.column();
|
||||
if (col >= 0 && col <= 5) {
|
||||
returnType = COBOLLINENUM;
|
||||
} else if (col >= 72 && col <= 79) {
|
||||
stream.skipToEnd();
|
||||
returnType = MODTAG;
|
||||
} else if (ch == "*" && col == 6) { // comment
|
||||
stream.skipToEnd(); // rest of the line is a comment
|
||||
returnType = COMMENT;
|
||||
} else if (ch == "\"" || ch == "\'") {
|
||||
state.mode = "string";
|
||||
returnType = STRING;
|
||||
} else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
|
||||
returnType = ATOM;
|
||||
} else if (ch == ".") {
|
||||
returnType = PERIOD;
|
||||
} else if (isNumber(ch,stream)){
|
||||
returnType = NUMBER;
|
||||
} else {
|
||||
if (stream.current().match(tests.symbol)) {
|
||||
while (col < 71) {
|
||||
if (stream.eat(tests.symbol) === undefined) {
|
||||
break;
|
||||
} else {
|
||||
col++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
|
||||
returnType = KEYWORD;
|
||||
} else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) {
|
||||
returnType = BUILTIN;
|
||||
} else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) {
|
||||
returnType = ATOM;
|
||||
} else returnType = null;
|
||||
}
|
||||
}
|
||||
return returnType;
|
||||
},
|
||||
indent: function (state) {
|
||||
if (state.indentStack == null) return state.indentation;
|
||||
return state.indentStack.indent;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-cobol", "cobol");
|
||||
|
||||
});
|
||||
@@ -0,0 +1,210 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: COBOL mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<link rel="stylesheet" href="../../theme/neat.css">
|
||||
<link rel="stylesheet" href="../../theme/elegant.css">
|
||||
<link rel="stylesheet" href="../../theme/erlang-dark.css">
|
||||
<link rel="stylesheet" href="../../theme/night.css">
|
||||
<link rel="stylesheet" href="../../theme/monokai.css">
|
||||
<link rel="stylesheet" href="../../theme/cobalt.css">
|
||||
<link rel="stylesheet" href="../../theme/eclipse.css">
|
||||
<link rel="stylesheet" href="../../theme/rubyblue.css">
|
||||
<link rel="stylesheet" href="../../theme/lesser-dark.css">
|
||||
<link rel="stylesheet" href="../../theme/xq-dark.css">
|
||||
<link rel="stylesheet" href="../../theme/xq-light.css">
|
||||
<link rel="stylesheet" href="../../theme/ambiance.css">
|
||||
<link rel="stylesheet" href="../../theme/blackboard.css">
|
||||
<link rel="stylesheet" href="../../theme/vibrant-ink.css">
|
||||
<link rel="stylesheet" href="../../theme/solarized.css">
|
||||
<link rel="stylesheet" href="../../theme/twilight.css">
|
||||
<link rel="stylesheet" href="../../theme/midnight.css">
|
||||
<link rel="stylesheet" href="../../addon/dialog/dialog.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="cobol.js"></script>
|
||||
<script src="../../addon/selection/active-line.js"></script>
|
||||
<script src="../../addon/search/search.js"></script>
|
||||
<script src="../../addon/dialog/dialog.js"></script>
|
||||
<script src="../../addon/search/searchcursor.js"></script>
|
||||
<style>
|
||||
.CodeMirror {
|
||||
border: 1px solid #eee;
|
||||
font-size : 20px;
|
||||
height : auto !important;
|
||||
}
|
||||
.CodeMirror-activeline-background {background: #555555 !important;}
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">COBOL</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>COBOL mode</h2>
|
||||
|
||||
<p> Select Theme <select onchange="selectTheme()" id="selectTheme">
|
||||
<option>default</option>
|
||||
<option>ambiance</option>
|
||||
<option>blackboard</option>
|
||||
<option>cobalt</option>
|
||||
<option>eclipse</option>
|
||||
<option>elegant</option>
|
||||
<option>erlang-dark</option>
|
||||
<option>lesser-dark</option>
|
||||
<option>midnight</option>
|
||||
<option>monokai</option>
|
||||
<option>neat</option>
|
||||
<option>night</option>
|
||||
<option>rubyblue</option>
|
||||
<option>solarized dark</option>
|
||||
<option>solarized light</option>
|
||||
<option selected>twilight</option>
|
||||
<option>vibrant-ink</option>
|
||||
<option>xq-dark</option>
|
||||
<option>xq-light</option>
|
||||
</select> Select Font Size <select onchange="selectFontsize()" id="selectFontSize">
|
||||
<option value="13px">13px</option>
|
||||
<option value="14px">14px</option>
|
||||
<option value="16px">16px</option>
|
||||
<option value="18px">18px</option>
|
||||
<option value="20px" selected="selected">20px</option>
|
||||
<option value="24px">24px</option>
|
||||
<option value="26px">26px</option>
|
||||
<option value="28px">28px</option>
|
||||
<option value="30px">30px</option>
|
||||
<option value="32px">32px</option>
|
||||
<option value="34px">34px</option>
|
||||
<option value="36px">36px</option>
|
||||
</select>
|
||||
<label for="checkBoxReadOnly">Read-only</label>
|
||||
<input type="checkbox" id="checkBoxReadOnly" onchange="selectReadOnly()">
|
||||
<label for="id_tabToIndentSpace">Insert Spaces on Tab</label>
|
||||
<input type="checkbox" id="id_tabToIndentSpace" onchange="tabToIndentSpace()">
|
||||
</p>
|
||||
<textarea id="code" name="code">
|
||||
---------1---------2---------3---------4---------5---------6---------7---------8
|
||||
12345678911234567892123456789312345678941234567895123456789612345678971234567898
|
||||
000010 IDENTIFICATION DIVISION. MODTGHERE
|
||||
000020 PROGRAM-ID. SAMPLE.
|
||||
000030 AUTHOR. TEST SAM.
|
||||
000040 DATE-WRITTEN. 5 February 2013
|
||||
000041
|
||||
000042* A sample program just to show the form.
|
||||
000043* The program copies its input to the output,
|
||||
000044* and counts the number of records.
|
||||
000045* At the end this number is printed.
|
||||
000046
|
||||
000050 ENVIRONMENT DIVISION.
|
||||
000060 INPUT-OUTPUT SECTION.
|
||||
000070 FILE-CONTROL.
|
||||
000080 SELECT STUDENT-FILE ASSIGN TO SYSIN
|
||||
000090 ORGANIZATION IS LINE SEQUENTIAL.
|
||||
000100 SELECT PRINT-FILE ASSIGN TO SYSOUT
|
||||
000110 ORGANIZATION IS LINE SEQUENTIAL.
|
||||
000120
|
||||
000130 DATA DIVISION.
|
||||
000140 FILE SECTION.
|
||||
000150 FD STUDENT-FILE
|
||||
000160 RECORD CONTAINS 43 CHARACTERS
|
||||
000170 DATA RECORD IS STUDENT-IN.
|
||||
000180 01 STUDENT-IN PIC X(43).
|
||||
000190
|
||||
000200 FD PRINT-FILE
|
||||
000210 RECORD CONTAINS 80 CHARACTERS
|
||||
000220 DATA RECORD IS PRINT-LINE.
|
||||
000230 01 PRINT-LINE PIC X(80).
|
||||
000240
|
||||
000250 WORKING-STORAGE SECTION.
|
||||
000260 01 DATA-REMAINS-SWITCH PIC X(2) VALUE SPACES.
|
||||
000261 01 RECORDS-WRITTEN PIC 99.
|
||||
000270
|
||||
000280 01 DETAIL-LINE.
|
||||
000290 05 FILLER PIC X(7) VALUE SPACES.
|
||||
000300 05 RECORD-IMAGE PIC X(43).
|
||||
000310 05 FILLER PIC X(30) VALUE SPACES.
|
||||
000311
|
||||
000312 01 SUMMARY-LINE.
|
||||
000313 05 FILLER PIC X(7) VALUE SPACES.
|
||||
000314 05 TOTAL-READ PIC 99.
|
||||
000315 05 FILLER PIC X VALUE SPACE.
|
||||
000316 05 FILLER PIC X(17)
|
||||
000317 VALUE 'Records were read'.
|
||||
000318 05 FILLER PIC X(53) VALUE SPACES.
|
||||
000319
|
||||
000320 PROCEDURE DIVISION.
|
||||
000321
|
||||
000330 PREPARE-SENIOR-REPORT.
|
||||
000340 OPEN INPUT STUDENT-FILE
|
||||
000350 OUTPUT PRINT-FILE.
|
||||
000351 MOVE ZERO TO RECORDS-WRITTEN.
|
||||
000360 READ STUDENT-FILE
|
||||
000370 AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
|
||||
000380 END-READ.
|
||||
000390 PERFORM PROCESS-RECORDS
|
||||
000410 UNTIL DATA-REMAINS-SWITCH = 'NO'.
|
||||
000411 PERFORM PRINT-SUMMARY.
|
||||
000420 CLOSE STUDENT-FILE
|
||||
000430 PRINT-FILE.
|
||||
000440 STOP RUN.
|
||||
000450
|
||||
000460 PROCESS-RECORDS.
|
||||
000470 MOVE STUDENT-IN TO RECORD-IMAGE.
|
||||
000480 MOVE DETAIL-LINE TO PRINT-LINE.
|
||||
000490 WRITE PRINT-LINE.
|
||||
000500 ADD 1 TO RECORDS-WRITTEN.
|
||||
000510 READ STUDENT-FILE
|
||||
000520 AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
|
||||
000530 END-READ.
|
||||
000540
|
||||
000550 PRINT-SUMMARY.
|
||||
000560 MOVE RECORDS-WRITTEN TO TOTAL-READ.
|
||||
000570 MOVE SUMMARY-LINE TO PRINT-LINE.
|
||||
000571 WRITE PRINT-LINE.
|
||||
000572
|
||||
000580
|
||||
</textarea>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-cobol",
|
||||
theme : "twilight",
|
||||
styleActiveLine: true,
|
||||
showCursorWhenSelecting : true,
|
||||
});
|
||||
function selectTheme() {
|
||||
var themeInput = document.getElementById("selectTheme");
|
||||
var theme = themeInput.options[themeInput.selectedIndex].innerHTML;
|
||||
editor.setOption("theme", theme);
|
||||
}
|
||||
function selectFontsize() {
|
||||
var fontSizeInput = document.getElementById("selectFontSize");
|
||||
var fontSize = fontSizeInput.options[fontSizeInput.selectedIndex].innerHTML;
|
||||
editor.getWrapperElement().style.fontSize = fontSize;
|
||||
editor.refresh();
|
||||
}
|
||||
function selectReadOnly() {
|
||||
editor.setOption("readOnly", document.getElementById("checkBoxReadOnly").checked);
|
||||
}
|
||||
function tabToIndentSpace() {
|
||||
if (document.getElementById("id_tabToIndentSpace").checked) {
|
||||
editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection(" ", "end"); }});
|
||||
} else {
|
||||
editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection(" ", "end"); }});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</article>
|
||||
@@ -0,0 +1,355 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/**
|
||||
* Link to the project's GitHub page:
|
||||
* https://github.com/pickhardt/coffeescript-codemirror-mode
|
||||
*/
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
|
||||
var ERRORCLASS = "error";
|
||||
|
||||
function wordRegexp(words) {
|
||||
return new RegExp("^((" + words.join(")|(") + "))\\b");
|
||||
}
|
||||
|
||||
var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
|
||||
var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
|
||||
var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
|
||||
var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/;
|
||||
|
||||
var wordOperators = wordRegexp(["and", "or", "not",
|
||||
"is", "isnt", "in",
|
||||
"instanceof", "typeof"]);
|
||||
var indentKeywords = ["for", "while", "loop", "if", "unless", "else",
|
||||
"switch", "try", "catch", "finally", "class"];
|
||||
var commonKeywords = ["break", "by", "continue", "debugger", "delete",
|
||||
"do", "in", "of", "new", "return", "then",
|
||||
"this", "@", "throw", "when", "until", "extends"];
|
||||
|
||||
var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
|
||||
|
||||
indentKeywords = wordRegexp(indentKeywords);
|
||||
|
||||
|
||||
var stringPrefixes = /^('{3}|\"{3}|['\"])/;
|
||||
var regexPrefixes = /^(\/{3}|\/)/;
|
||||
var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"];
|
||||
var constants = wordRegexp(commonConstants);
|
||||
|
||||
// Tokenizers
|
||||
function tokenBase(stream, state) {
|
||||
// Handle scope changes
|
||||
if (stream.sol()) {
|
||||
if (state.scope.align === null) state.scope.align = false;
|
||||
var scopeOffset = state.scope.offset;
|
||||
if (stream.eatSpace()) {
|
||||
var lineOffset = stream.indentation();
|
||||
if (lineOffset > scopeOffset && state.scope.type == "coffee") {
|
||||
return "indent";
|
||||
} else if (lineOffset < scopeOffset) {
|
||||
return "dedent";
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
if (scopeOffset > 0) {
|
||||
dedent(stream, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var ch = stream.peek();
|
||||
|
||||
// Handle docco title comment (single line)
|
||||
if (stream.match("####")) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
|
||||
// Handle multi line comments
|
||||
if (stream.match("###")) {
|
||||
state.tokenize = longComment;
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
|
||||
// Single line comment
|
||||
if (ch === "#") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
|
||||
// Handle number literals
|
||||
if (stream.match(/^-?[0-9\.]/, false)) {
|
||||
var floatLiteral = false;
|
||||
// Floats
|
||||
if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
|
||||
floatLiteral = true;
|
||||
}
|
||||
if (stream.match(/^-?\d+\.\d*/)) {
|
||||
floatLiteral = true;
|
||||
}
|
||||
if (stream.match(/^-?\.\d+/)) {
|
||||
floatLiteral = true;
|
||||
}
|
||||
|
||||
if (floatLiteral) {
|
||||
// prevent from getting extra . on 1..
|
||||
if (stream.peek() == "."){
|
||||
stream.backUp(1);
|
||||
}
|
||||
return "number";
|
||||
}
|
||||
// Integers
|
||||
var intLiteral = false;
|
||||
// Hex
|
||||
if (stream.match(/^-?0x[0-9a-f]+/i)) {
|
||||
intLiteral = true;
|
||||
}
|
||||
// Decimal
|
||||
if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
|
||||
intLiteral = true;
|
||||
}
|
||||
// Zero by itself with no other piece of number.
|
||||
if (stream.match(/^-?0(?![\dx])/i)) {
|
||||
intLiteral = true;
|
||||
}
|
||||
if (intLiteral) {
|
||||
return "number";
|
||||
}
|
||||
}
|
||||
|
||||
// Handle strings
|
||||
if (stream.match(stringPrefixes)) {
|
||||
state.tokenize = tokenFactory(stream.current(), false, "string");
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
// Handle regex literals
|
||||
if (stream.match(regexPrefixes)) {
|
||||
if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division
|
||||
state.tokenize = tokenFactory(stream.current(), true, "string-2");
|
||||
return state.tokenize(stream, state);
|
||||
} else {
|
||||
stream.backUp(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Handle operators and delimiters
|
||||
if (stream.match(operators) || stream.match(wordOperators)) {
|
||||
return "operator";
|
||||
}
|
||||
if (stream.match(delimiters)) {
|
||||
return "punctuation";
|
||||
}
|
||||
|
||||
if (stream.match(constants)) {
|
||||
return "atom";
|
||||
}
|
||||
|
||||
if (stream.match(atProp) || state.prop && stream.match(identifiers)) {
|
||||
return "property";
|
||||
}
|
||||
|
||||
if (stream.match(keywords)) {
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
if (stream.match(identifiers)) {
|
||||
return "variable";
|
||||
}
|
||||
|
||||
// Handle non-detected items
|
||||
stream.next();
|
||||
return ERRORCLASS;
|
||||
}
|
||||
|
||||
function tokenFactory(delimiter, singleline, outclass) {
|
||||
return function(stream, state) {
|
||||
while (!stream.eol()) {
|
||||
stream.eatWhile(/[^'"\/\\]/);
|
||||
if (stream.eat("\\")) {
|
||||
stream.next();
|
||||
if (singleline && stream.eol()) {
|
||||
return outclass;
|
||||
}
|
||||
} else if (stream.match(delimiter)) {
|
||||
state.tokenize = tokenBase;
|
||||
return outclass;
|
||||
} else {
|
||||
stream.eat(/['"\/]/);
|
||||
}
|
||||
}
|
||||
if (singleline) {
|
||||
if (parserConf.singleLineStringErrors) {
|
||||
outclass = ERRORCLASS;
|
||||
} else {
|
||||
state.tokenize = tokenBase;
|
||||
}
|
||||
}
|
||||
return outclass;
|
||||
};
|
||||
}
|
||||
|
||||
function longComment(stream, state) {
|
||||
while (!stream.eol()) {
|
||||
stream.eatWhile(/[^#]/);
|
||||
if (stream.match("###")) {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
stream.eatWhile("#");
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
|
||||
function indent(stream, state, type) {
|
||||
type = type || "coffee";
|
||||
var offset = 0, align = false, alignOffset = null;
|
||||
for (var scope = state.scope; scope; scope = scope.prev) {
|
||||
if (scope.type === "coffee" || scope.type == "}") {
|
||||
offset = scope.offset + conf.indentUnit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type !== "coffee") {
|
||||
align = null;
|
||||
alignOffset = stream.column() + stream.current().length;
|
||||
} else if (state.scope.align) {
|
||||
state.scope.align = false;
|
||||
}
|
||||
state.scope = {
|
||||
offset: offset,
|
||||
type: type,
|
||||
prev: state.scope,
|
||||
align: align,
|
||||
alignOffset: alignOffset
|
||||
};
|
||||
}
|
||||
|
||||
function dedent(stream, state) {
|
||||
if (!state.scope.prev) return;
|
||||
if (state.scope.type === "coffee") {
|
||||
var _indent = stream.indentation();
|
||||
var matched = false;
|
||||
for (var scope = state.scope; scope; scope = scope.prev) {
|
||||
if (_indent === scope.offset) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched) {
|
||||
return true;
|
||||
}
|
||||
while (state.scope.prev && state.scope.offset !== _indent) {
|
||||
state.scope = state.scope.prev;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
state.scope = state.scope.prev;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function tokenLexer(stream, state) {
|
||||
var style = state.tokenize(stream, state);
|
||||
var current = stream.current();
|
||||
|
||||
// Handle scope changes.
|
||||
if (current === "return") {
|
||||
state.dedent = true;
|
||||
}
|
||||
if (((current === "->" || current === "=>") && stream.eol())
|
||||
|| style === "indent") {
|
||||
indent(stream, state);
|
||||
}
|
||||
var delimiter_index = "[({".indexOf(current);
|
||||
if (delimiter_index !== -1) {
|
||||
indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
|
||||
}
|
||||
if (indentKeywords.exec(current)){
|
||||
indent(stream, state);
|
||||
}
|
||||
if (current == "then"){
|
||||
dedent(stream, state);
|
||||
}
|
||||
|
||||
|
||||
if (style === "dedent") {
|
||||
if (dedent(stream, state)) {
|
||||
return ERRORCLASS;
|
||||
}
|
||||
}
|
||||
delimiter_index = "])}".indexOf(current);
|
||||
if (delimiter_index !== -1) {
|
||||
while (state.scope.type == "coffee" && state.scope.prev)
|
||||
state.scope = state.scope.prev;
|
||||
if (state.scope.type == current)
|
||||
state.scope = state.scope.prev;
|
||||
}
|
||||
if (state.dedent && stream.eol()) {
|
||||
if (state.scope.type == "coffee" && state.scope.prev)
|
||||
state.scope = state.scope.prev;
|
||||
state.dedent = false;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
var external = {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: tokenBase,
|
||||
scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
|
||||
prop: false,
|
||||
dedent: 0
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
var fillAlign = state.scope.align === null && state.scope;
|
||||
if (fillAlign && stream.sol()) fillAlign.align = false;
|
||||
|
||||
var style = tokenLexer(stream, state);
|
||||
if (style && style != "comment") {
|
||||
if (fillAlign) fillAlign.align = true;
|
||||
state.prop = style == "punctuation" && stream.current() == "."
|
||||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, text) {
|
||||
if (state.tokenize != tokenBase) return 0;
|
||||
var scope = state.scope;
|
||||
var closer = text && "])}".indexOf(text.charAt(0)) > -1;
|
||||
if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev;
|
||||
var closes = closer && scope.type === text.charAt(0);
|
||||
if (scope.align)
|
||||
return scope.alignOffset - (closes ? 1 : 0);
|
||||
else
|
||||
return (closes ? scope.prev : scope).offset;
|
||||
},
|
||||
|
||||
lineComment: "#",
|
||||
fold: "indent"
|
||||
};
|
||||
return external;
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
|
||||
CodeMirror.defineMIME("text/coffeescript", "coffeescript");
|
||||
|
||||
});
|
||||
@@ -0,0 +1,740 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: CoffeeScript mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="coffeescript.js"></script>
|
||||
<style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">CoffeeScript</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>CoffeeScript mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
# CoffeeScript mode for CodeMirror
|
||||
# Copyright (c) 2011 Jeff Pickhardt, released under
|
||||
# the MIT License.
|
||||
#
|
||||
# Modified from the Python CodeMirror mode, which also is
|
||||
# under the MIT License Copyright (c) 2010 Timothy Farrell.
|
||||
#
|
||||
# The following script, Underscore.coffee, is used to
|
||||
# demonstrate CoffeeScript mode for CodeMirror.
|
||||
#
|
||||
# To download CoffeeScript mode for CodeMirror, go to:
|
||||
# https://github.com/pickhardt/coffeescript-codemirror-mode
|
||||
|
||||
# **Underscore.coffee
|
||||
# (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**
|
||||
# Underscore is freely distributable under the terms of the
|
||||
# [MIT license](http://en.wikipedia.org/wiki/MIT_License).
|
||||
# Portions of Underscore are inspired by or borrowed from
|
||||
# [Prototype.js](http://prototypejs.org/api), Oliver Steele's
|
||||
# [Functional](http://osteele.com), and John Resig's
|
||||
# [Micro-Templating](http://ejohn.org).
|
||||
# For all details and documentation:
|
||||
# http://documentcloud.github.com/underscore/
|
||||
|
||||
|
||||
# Baseline setup
|
||||
# --------------
|
||||
|
||||
# Establish the root object, `window` in the browser, or `global` on the server.
|
||||
root = this
|
||||
|
||||
|
||||
# Save the previous value of the `_` variable.
|
||||
previousUnderscore = root._
|
||||
|
||||
### Multiline
|
||||
comment
|
||||
###
|
||||
|
||||
# Establish the object that gets thrown to break out of a loop iteration.
|
||||
# `StopIteration` is SOP on Mozilla.
|
||||
breaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
|
||||
|
||||
|
||||
#### Docco style single line comment (title)
|
||||
|
||||
|
||||
# Helper function to escape **RegExp** contents, because JS doesn't have one.
|
||||
escapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
|
||||
|
||||
|
||||
# Save bytes in the minified (but not gzipped) version:
|
||||
ArrayProto = Array.prototype
|
||||
ObjProto = Object.prototype
|
||||
|
||||
|
||||
# Create quick reference variables for speed access to core prototypes.
|
||||
slice = ArrayProto.slice
|
||||
unshift = ArrayProto.unshift
|
||||
toString = ObjProto.toString
|
||||
hasOwnProperty = ObjProto.hasOwnProperty
|
||||
propertyIsEnumerable = ObjProto.propertyIsEnumerable
|
||||
|
||||
|
||||
# All **ECMA5** native implementations we hope to use are declared here.
|
||||
nativeForEach = ArrayProto.forEach
|
||||
nativeMap = ArrayProto.map
|
||||
nativeReduce = ArrayProto.reduce
|
||||
nativeReduceRight = ArrayProto.reduceRight
|
||||
nativeFilter = ArrayProto.filter
|
||||
nativeEvery = ArrayProto.every
|
||||
nativeSome = ArrayProto.some
|
||||
nativeIndexOf = ArrayProto.indexOf
|
||||
nativeLastIndexOf = ArrayProto.lastIndexOf
|
||||
nativeIsArray = Array.isArray
|
||||
nativeKeys = Object.keys
|
||||
|
||||
|
||||
# Create a safe reference to the Underscore object for use below.
|
||||
_ = (obj) -> new wrapper(obj)
|
||||
|
||||
|
||||
# Export the Underscore object for **CommonJS**.
|
||||
if typeof(exports) != 'undefined' then exports._ = _
|
||||
|
||||
|
||||
# Export Underscore to global scope.
|
||||
root._ = _
|
||||
|
||||
|
||||
# Current version.
|
||||
_.VERSION = '1.1.0'
|
||||
|
||||
|
||||
# Collection Functions
|
||||
# --------------------
|
||||
|
||||
# The cornerstone, an **each** implementation.
|
||||
# Handles objects implementing **forEach**, arrays, and raw objects.
|
||||
_.each = (obj, iterator, context) ->
|
||||
try
|
||||
if nativeForEach and obj.forEach is nativeForEach
|
||||
obj.forEach iterator, context
|
||||
else if _.isNumber obj.length
|
||||
iterator.call context, obj[i], i, obj for i in [0...obj.length]
|
||||
else
|
||||
iterator.call context, val, key, obj for own key, val of obj
|
||||
catch e
|
||||
throw e if e isnt breaker
|
||||
obj
|
||||
|
||||
|
||||
# Return the results of applying the iterator to each element. Use JavaScript
|
||||
# 1.6's version of **map**, if possible.
|
||||
_.map = (obj, iterator, context) ->
|
||||
return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# **Reduce** builds up a single result from a list of values. Also known as
|
||||
# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
|
||||
_.reduce = (obj, iterator, memo, context) ->
|
||||
if nativeReduce and obj.reduce is nativeReduce
|
||||
iterator = _.bind iterator, context if context
|
||||
return obj.reduce iterator, memo
|
||||
_.each obj, (value, index, list) ->
|
||||
memo = iterator.call context, memo, value, index, list
|
||||
memo
|
||||
|
||||
|
||||
# The right-associative version of **reduce**, also known as **foldr**. Uses
|
||||
# JavaScript 1.8's version of **reduceRight**, if available.
|
||||
_.reduceRight = (obj, iterator, memo, context) ->
|
||||
if nativeReduceRight and obj.reduceRight is nativeReduceRight
|
||||
iterator = _.bind iterator, context if context
|
||||
return obj.reduceRight iterator, memo
|
||||
reversed = _.clone(_.toArray(obj)).reverse()
|
||||
_.reduce reversed, iterator, memo, context
|
||||
|
||||
|
||||
# Return the first value which passes a truth test.
|
||||
_.detect = (obj, iterator, context) ->
|
||||
result = null
|
||||
_.each obj, (value, index, list) ->
|
||||
if iterator.call context, value, index, list
|
||||
result = value
|
||||
_.breakLoop()
|
||||
result
|
||||
|
||||
|
||||
# Return all the elements that pass a truth test. Use JavaScript 1.6's
|
||||
# **filter**, if it exists.
|
||||
_.filter = (obj, iterator, context) ->
|
||||
return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push value if iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# Return all the elements for which a truth test fails.
|
||||
_.reject = (obj, iterator, context) ->
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push value if not iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# Determine whether all of the elements match a truth test. Delegate to
|
||||
# JavaScript 1.6's **every**, if it is present.
|
||||
_.every = (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
|
||||
result = true
|
||||
_.each obj, (value, index, list) ->
|
||||
_.breakLoop() unless (result = result and iterator.call(context, value, index, list))
|
||||
result
|
||||
|
||||
|
||||
# Determine if at least one element in the object matches a truth test. Use
|
||||
# JavaScript 1.6's **some**, if it exists.
|
||||
_.some = (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.some iterator, context if nativeSome and obj.some is nativeSome
|
||||
result = false
|
||||
_.each obj, (value, index, list) ->
|
||||
_.breakLoop() if (result = iterator.call(context, value, index, list))
|
||||
result
|
||||
|
||||
|
||||
# Determine if a given value is included in the array or object,
|
||||
# based on `===`.
|
||||
_.include = (obj, target) ->
|
||||
return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
|
||||
return true for own key, val of obj when val is target
|
||||
false
|
||||
|
||||
|
||||
# Invoke a method with arguments on every item in a collection.
|
||||
_.invoke = (obj, method) ->
|
||||
args = _.rest arguments, 2
|
||||
(if method then val[method] else val).apply(val, args) for val in obj
|
||||
|
||||
|
||||
# Convenience version of a common use case of **map**: fetching a property.
|
||||
_.pluck = (obj, key) ->
|
||||
_.map(obj, (val) -> val[key])
|
||||
|
||||
|
||||
# Return the maximum item or (item-based computation).
|
||||
_.max = (obj, iterator, context) ->
|
||||
return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
|
||||
result = computed: -Infinity
|
||||
_.each obj, (value, index, list) ->
|
||||
computed = if iterator then iterator.call(context, value, index, list) else value
|
||||
computed >= result.computed and (result = {value: value, computed: computed})
|
||||
result.value
|
||||
|
||||
|
||||
# Return the minimum element (or element-based computation).
|
||||
_.min = (obj, iterator, context) ->
|
||||
return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
|
||||
result = computed: Infinity
|
||||
_.each obj, (value, index, list) ->
|
||||
computed = if iterator then iterator.call(context, value, index, list) else value
|
||||
computed < result.computed and (result = {value: value, computed: computed})
|
||||
result.value
|
||||
|
||||
|
||||
# Sort the object's values by a criterion produced by an iterator.
|
||||
_.sortBy = (obj, iterator, context) ->
|
||||
_.pluck(((_.map obj, (value, index, list) ->
|
||||
{value: value, criteria: iterator.call(context, value, index, list)}
|
||||
).sort((left, right) ->
|
||||
a = left.criteria; b = right.criteria
|
||||
if a < b then -1 else if a > b then 1 else 0
|
||||
)), 'value')
|
||||
|
||||
|
||||
# Use a comparator function to figure out at what index an object should
|
||||
# be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex = (array, obj, iterator) ->
|
||||
iterator ||= _.identity
|
||||
low = 0
|
||||
high = array.length
|
||||
while low < high
|
||||
mid = (low + high) >> 1
|
||||
if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid
|
||||
low
|
||||
|
||||
|
||||
# Convert anything iterable into a real, live array.
|
||||
_.toArray = (iterable) ->
|
||||
return [] if (!iterable)
|
||||
return iterable.toArray() if (iterable.toArray)
|
||||
return iterable if (_.isArray(iterable))
|
||||
return slice.call(iterable) if (_.isArguments(iterable))
|
||||
_.values(iterable)
|
||||
|
||||
|
||||
# Return the number of elements in an object.
|
||||
_.size = (obj) -> _.toArray(obj).length
|
||||
|
||||
|
||||
# Array Functions
|
||||
# ---------------
|
||||
|
||||
# Get the first element of an array. Passing `n` will return the first N
|
||||
# values in the array. Aliased as **head**. The `guard` check allows it to work
|
||||
# with **map**.
|
||||
_.first = (array, n, guard) ->
|
||||
if n and not guard then slice.call(array, 0, n) else array[0]
|
||||
|
||||
|
||||
# Returns everything but the first entry of the array. Aliased as **tail**.
|
||||
# Especially useful on the arguments object. Passing an `index` will return
|
||||
# the rest of the values in the array from that index onward. The `guard`
|
||||
# check allows it to work with **map**.
|
||||
_.rest = (array, index, guard) ->
|
||||
slice.call(array, if _.isUndefined(index) or guard then 1 else index)
|
||||
|
||||
|
||||
# Get the last element of an array.
|
||||
_.last = (array) -> array[array.length - 1]
|
||||
|
||||
|
||||
# Trim out all falsy values from an array.
|
||||
_.compact = (array) -> item for item in array when item
|
||||
|
||||
|
||||
# Return a completely flattened version of an array.
|
||||
_.flatten = (array) ->
|
||||
_.reduce array, (memo, value) ->
|
||||
return memo.concat(_.flatten(value)) if _.isArray value
|
||||
memo.push value
|
||||
memo
|
||||
, []
|
||||
|
||||
|
||||
# Return a version of the array that does not contain the specified value(s).
|
||||
_.without = (array) ->
|
||||
values = _.rest arguments
|
||||
val for val in _.toArray(array) when not _.include values, val
|
||||
|
||||
|
||||
# Produce a duplicate-free version of the array. If the array has already
|
||||
# been sorted, you have the option of using a faster algorithm.
|
||||
_.uniq = (array, isSorted) ->
|
||||
memo = []
|
||||
for el, i in _.toArray array
|
||||
memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
|
||||
memo
|
||||
|
||||
|
||||
# Produce an array that contains every item shared between all the
|
||||
# passed-in arrays.
|
||||
_.intersect = (array) ->
|
||||
rest = _.rest arguments
|
||||
_.select _.uniq(array), (item) ->
|
||||
_.all rest, (other) ->
|
||||
_.indexOf(other, item) >= 0
|
||||
|
||||
|
||||
# Zip together multiple lists into a single array -- elements that share
|
||||
# an index go together.
|
||||
_.zip = ->
|
||||
length = _.max _.pluck arguments, 'length'
|
||||
results = new Array length
|
||||
for i in [0...length]
|
||||
results[i] = _.pluck arguments, String i
|
||||
results
|
||||
|
||||
|
||||
# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
|
||||
# we need this function. Return the position of the first occurrence of an
|
||||
# item in an array, or -1 if the item is not included in the array.
|
||||
_.indexOf = (array, item) ->
|
||||
return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
|
||||
i = 0; l = array.length
|
||||
while l - i
|
||||
if array[i] is item then return i else i++
|
||||
-1
|
||||
|
||||
|
||||
# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
|
||||
# if possible.
|
||||
_.lastIndexOf = (array, item) ->
|
||||
return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
|
||||
i = array.length
|
||||
while i
|
||||
if array[i] is item then return i else i--
|
||||
-1
|
||||
|
||||
|
||||
# Generate an integer Array containing an arithmetic progression. A port of
|
||||
# [the native Python **range** function](http://docs.python.org/library/functions.html#range).
|
||||
_.range = (start, stop, step) ->
|
||||
a = arguments
|
||||
solo = a.length <= 1
|
||||
i = start = if solo then 0 else a[0]
|
||||
stop = if solo then a[0] else a[1]
|
||||
step = a[2] or 1
|
||||
len = Math.ceil((stop - start) / step)
|
||||
return [] if len <= 0
|
||||
range = new Array len
|
||||
idx = 0
|
||||
loop
|
||||
return range if (if step > 0 then i - stop else stop - i) >= 0
|
||||
range[idx] = i
|
||||
idx++
|
||||
i+= step
|
||||
|
||||
|
||||
# Function Functions
|
||||
# ------------------
|
||||
|
||||
# Create a function bound to a given object (assigning `this`, and arguments,
|
||||
# optionally). Binding with arguments is also known as **curry**.
|
||||
_.bind = (func, obj) ->
|
||||
args = _.rest arguments, 2
|
||||
-> func.apply obj or root, args.concat arguments
|
||||
|
||||
|
||||
# Bind all of an object's methods to that object. Useful for ensuring that
|
||||
# all callbacks defined on an object belong to it.
|
||||
_.bindAll = (obj) ->
|
||||
funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
|
||||
_.each funcs, (f) -> obj[f] = _.bind obj[f], obj
|
||||
obj
|
||||
|
||||
|
||||
# Delays a function for the given number of milliseconds, and then calls
|
||||
# it with the arguments supplied.
|
||||
_.delay = (func, wait) ->
|
||||
args = _.rest arguments, 2
|
||||
setTimeout((-> func.apply(func, args)), wait)
|
||||
|
||||
|
||||
# Memoize an expensive function by storing its results.
|
||||
_.memoize = (func, hasher) ->
|
||||
memo = {}
|
||||
hasher or= _.identity
|
||||
->
|
||||
key = hasher.apply this, arguments
|
||||
return memo[key] if key of memo
|
||||
memo[key] = func.apply this, arguments
|
||||
|
||||
|
||||
# Defers a function, scheduling it to run after the current call stack has
|
||||
# cleared.
|
||||
_.defer = (func) ->
|
||||
_.delay.apply _, [func, 1].concat _.rest arguments
|
||||
|
||||
|
||||
# Returns the first function passed as an argument to the second,
|
||||
# allowing you to adjust arguments, run code before and after, and
|
||||
# conditionally execute the original function.
|
||||
_.wrap = (func, wrapper) ->
|
||||
-> wrapper.apply wrapper, [func].concat arguments
|
||||
|
||||
|
||||
# Returns a function that is the composition of a list of functions, each
|
||||
# consuming the return value of the function that follows.
|
||||
_.compose = ->
|
||||
funcs = arguments
|
||||
->
|
||||
args = arguments
|
||||
for i in [funcs.length - 1..0] by -1
|
||||
args = [funcs[i].apply(this, args)]
|
||||
args[0]
|
||||
|
||||
|
||||
# Object Functions
|
||||
# ----------------
|
||||
|
||||
# Retrieve the names of an object's properties.
|
||||
_.keys = nativeKeys or (obj) ->
|
||||
return _.range 0, obj.length if _.isArray(obj)
|
||||
key for key, val of obj
|
||||
|
||||
|
||||
# Retrieve the values of an object's properties.
|
||||
_.values = (obj) ->
|
||||
_.map obj, _.identity
|
||||
|
||||
|
||||
# Return a sorted list of the function names available in Underscore.
|
||||
_.functions = (obj) ->
|
||||
_.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
|
||||
|
||||
|
||||
# Extend a given object with all of the properties in a source object.
|
||||
_.extend = (obj) ->
|
||||
for source in _.rest(arguments)
|
||||
obj[key] = val for key, val of source
|
||||
obj
|
||||
|
||||
|
||||
# Create a (shallow-cloned) duplicate of an object.
|
||||
_.clone = (obj) ->
|
||||
return obj.slice 0 if _.isArray obj
|
||||
_.extend {}, obj
|
||||
|
||||
|
||||
# Invokes interceptor with the obj, and then returns obj.
|
||||
# The primary purpose of this method is to "tap into" a method chain,
|
||||
# in order to perform operations on intermediate results within
|
||||
the chain.
|
||||
_.tap = (obj, interceptor) ->
|
||||
interceptor obj
|
||||
obj
|
||||
|
||||
|
||||
# Perform a deep comparison to check if two objects are equal.
|
||||
_.isEqual = (a, b) ->
|
||||
# Check object identity.
|
||||
return true if a is b
|
||||
# Different types?
|
||||
atype = typeof(a); btype = typeof(b)
|
||||
return false if atype isnt btype
|
||||
# Basic equality test (watch out for coercions).
|
||||
return true if `a == b`
|
||||
# One is falsy and the other truthy.
|
||||
return false if (!a and b) or (a and !b)
|
||||
# One of them implements an `isEqual()`?
|
||||
return a.isEqual(b) if a.isEqual
|
||||
# Check dates' integer values.
|
||||
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
|
||||
# Both are NaN?
|
||||
return false if _.isNaN(a) and _.isNaN(b)
|
||||
# Compare regular expressions.
|
||||
if _.isRegExp(a) and _.isRegExp(b)
|
||||
return a.source is b.source and
|
||||
a.global is b.global and
|
||||
a.ignoreCase is b.ignoreCase and
|
||||
a.multiline is b.multiline
|
||||
# If a is not an object by this point, we can't handle it.
|
||||
return false if atype isnt 'object'
|
||||
# Check for different array lengths before comparing contents.
|
||||
return false if a.length and (a.length isnt b.length)
|
||||
# Nothing else worked, deep compare the contents.
|
||||
aKeys = _.keys(a); bKeys = _.keys(b)
|
||||
# Different object sizes?
|
||||
return false if aKeys.length isnt bKeys.length
|
||||
# Recursive comparison of contents.
|
||||
return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
|
||||
true
|
||||
|
||||
|
||||
# Is a given array or object empty?
|
||||
_.isEmpty = (obj) ->
|
||||
return obj.length is 0 if _.isArray(obj) or _.isString(obj)
|
||||
return false for own key of obj
|
||||
true
|
||||
|
||||
|
||||
# Is a given value a DOM element?
|
||||
_.isElement = (obj) -> obj and obj.nodeType is 1
|
||||
|
||||
|
||||
# Is a given value an array?
|
||||
_.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
|
||||
|
||||
|
||||
# Is a given variable an arguments object?
|
||||
_.isArguments = (obj) -> obj and obj.callee
|
||||
|
||||
|
||||
# Is the given value a function?
|
||||
_.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)
|
||||
|
||||
|
||||
# Is the given value a string?
|
||||
_.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
|
||||
|
||||
|
||||
# Is a given value a number?
|
||||
_.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
|
||||
|
||||
|
||||
# Is a given value a boolean?
|
||||
_.isBoolean = (obj) -> obj is true or obj is false
|
||||
|
||||
|
||||
# Is a given value a Date?
|
||||
_.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
|
||||
|
||||
|
||||
# Is the given value a regular expression?
|
||||
_.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
|
||||
|
||||
|
||||
# Is the given value NaN -- this one is interesting. `NaN != NaN`, and
|
||||
# `isNaN(undefined) == true`, so we make sure it's a number first.
|
||||
_.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)
|
||||
|
||||
|
||||
# Is a given value equal to null?
|
||||
_.isNull = (obj) -> obj is null
|
||||
|
||||
|
||||
# Is a given variable undefined?
|
||||
_.isUndefined = (obj) -> typeof obj is 'undefined'
|
||||
|
||||
|
||||
# Utility Functions
|
||||
# -----------------
|
||||
|
||||
# Run Underscore.js in noConflict mode, returning the `_` variable to its
|
||||
# previous owner. Returns a reference to the Underscore object.
|
||||
_.noConflict = ->
|
||||
root._ = previousUnderscore
|
||||
this
|
||||
|
||||
|
||||
# Keep the identity function around for default iterators.
|
||||
_.identity = (value) -> value
|
||||
|
||||
|
||||
# Run a function `n` times.
|
||||
_.times = (n, iterator, context) ->
|
||||
iterator.call context, i for i in [0...n]
|
||||
|
||||
|
||||
# Break out of the middle of an iteration.
|
||||
_.breakLoop = -> throw breaker
|
||||
|
||||
|
||||
# Add your own custom functions to the Underscore object, ensuring that
|
||||
# they're correctly added to the OOP wrapper as well.
|
||||
_.mixin = (obj) ->
|
||||
for name in _.functions(obj)
|
||||
addToWrapper name, _[name] = obj[name]
|
||||
|
||||
|
||||
# Generate a unique integer id (unique within the entire client session).
|
||||
# Useful for temporary DOM ids.
|
||||
idCounter = 0
|
||||
_.uniqueId = (prefix) ->
|
||||
(prefix or '') + idCounter++
|
||||
|
||||
|
||||
# By default, Underscore uses **ERB**-style template delimiters, change the
|
||||
# following template settings to use alternative delimiters.
|
||||
_.templateSettings = {
|
||||
start: '<%'
|
||||
end: '%>'
|
||||
interpolate: /<%=(.+?)%>/g
|
||||
}
|
||||
|
||||
|
||||
# JavaScript templating a-la **ERB**, pilfered from John Resig's
|
||||
# *Secrets of the JavaScript Ninja*, page 83.
|
||||
# Single-quote fix from Rick Strahl.
|
||||
# With alterations for arbitrary delimiters, and to preserve whitespace.
|
||||
_.template = (str, data) ->
|
||||
c = _.templateSettings
|
||||
endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
|
||||
fn = new Function 'obj',
|
||||
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
||||
'with(obj||{}){p.push(\'' +
|
||||
str.replace(/\r/g, '\\r')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\t/g, '\\t')
|
||||
.replace(endMatch,"���")
|
||||
.split("'").join("\\'")
|
||||
.split("���").join("'")
|
||||
.replace(c.interpolate, "',$1,'")
|
||||
.split(c.start).join("');")
|
||||
.split(c.end).join("p.push('") +
|
||||
"');}return p.join('');"
|
||||
if data then fn(data) else fn
|
||||
|
||||
|
||||
# Aliases
|
||||
# -------
|
||||
|
||||
_.forEach = _.each
|
||||
_.foldl = _.inject = _.reduce
|
||||
_.foldr = _.reduceRight
|
||||
_.select = _.filter
|
||||
_.all = _.every
|
||||
_.any = _.some
|
||||
_.contains = _.include
|
||||
_.head = _.first
|
||||
_.tail = _.rest
|
||||
_.methods = _.functions
|
||||
|
||||
|
||||
# Setup the OOP Wrapper
|
||||
# ---------------------
|
||||
|
||||
# If Underscore is called as a function, it returns a wrapped object that
|
||||
# can be used OO-style. This wrapper holds altered versions of all the
|
||||
# underscore functions. Wrapped objects may be chained.
|
||||
wrapper = (obj) ->
|
||||
this._wrapped = obj
|
||||
this
|
||||
|
||||
|
||||
# Helper function to continue chaining intermediate results.
|
||||
result = (obj, chain) ->
|
||||
if chain then _(obj).chain() else obj
|
||||
|
||||
|
||||
# A method to easily add functions to the OOP wrapper.
|
||||
addToWrapper = (name, func) ->
|
||||
wrapper.prototype[name] = ->
|
||||
args = _.toArray arguments
|
||||
unshift.call args, this._wrapped
|
||||
result func.apply(_, args), this._chain
|
||||
|
||||
|
||||
# Add all ofthe Underscore functions to the wrapper object.
|
||||
_.mixin _
|
||||
|
||||
|
||||
# Add all mutator Array functions to the wrapper.
|
||||
_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
|
||||
method = Array.prototype[name]
|
||||
wrapper.prototype[name] = ->
|
||||
method.apply(this._wrapped, arguments)
|
||||
result(this._wrapped, this._chain)
|
||||
|
||||
|
||||
# Add all accessor Array functions to the wrapper.
|
||||
_.each ['concat', 'join', 'slice'], (name) ->
|
||||
method = Array.prototype[name]
|
||||
wrapper.prototype[name] = ->
|
||||
result(method.apply(this._wrapped, arguments), this._chain)
|
||||
|
||||
|
||||
# Start chaining a wrapped Underscore object.
|
||||
wrapper::chain = ->
|
||||
this._chain = true
|
||||
this
|
||||
|
||||
|
||||
# Extracts the result from a wrapped and chained object.
|
||||
wrapper::value = -> this._wrapped
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>
|
||||
|
||||
<p>The CoffeeScript mode was written by Jeff Pickhardt.</p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,123 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("commonlisp", function (config) {
|
||||
var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/;
|
||||
var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;
|
||||
var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/;
|
||||
var symbol = /[^\s'`,@()\[\]";]/;
|
||||
var type;
|
||||
|
||||
function readSym(stream) {
|
||||
var ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "\\") stream.next();
|
||||
else if (!symbol.test(ch)) { stream.backUp(1); break; }
|
||||
}
|
||||
return stream.current();
|
||||
}
|
||||
|
||||
function base(stream, state) {
|
||||
if (stream.eatSpace()) {type = "ws"; return null;}
|
||||
if (stream.match(numLiteral)) return "number";
|
||||
var ch = stream.next();
|
||||
if (ch == "\\") ch = stream.next();
|
||||
|
||||
if (ch == '"') return (state.tokenize = inString)(stream, state);
|
||||
else if (ch == "(") { type = "open"; return "bracket"; }
|
||||
else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; }
|
||||
else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; }
|
||||
else if (/['`,@]/.test(ch)) return null;
|
||||
else if (ch == "|") {
|
||||
if (stream.skipTo("|")) { stream.next(); return "symbol"; }
|
||||
else { stream.skipToEnd(); return "error"; }
|
||||
} else if (ch == "#") {
|
||||
var ch = stream.next();
|
||||
if (ch == "[") { type = "open"; return "bracket"; }
|
||||
else if (/[+\-=\.']/.test(ch)) return null;
|
||||
else if (/\d/.test(ch) && stream.match(/^\d*#/)) return null;
|
||||
else if (ch == "|") return (state.tokenize = inComment)(stream, state);
|
||||
else if (ch == ":") { readSym(stream); return "meta"; }
|
||||
else return "error";
|
||||
} else {
|
||||
var name = readSym(stream);
|
||||
if (name == ".") return null;
|
||||
type = "symbol";
|
||||
if (name == "nil" || name == "t" || name.charAt(0) == ":") return "atom";
|
||||
if (state.lastType == "open" && (specialForm.test(name) || assumeBody.test(name))) return "keyword";
|
||||
if (name.charAt(0) == "&") return "variable-2";
|
||||
return "variable";
|
||||
}
|
||||
}
|
||||
|
||||
function inString(stream, state) {
|
||||
var escaped = false, next;
|
||||
while (next = stream.next()) {
|
||||
if (next == '"' && !escaped) { state.tokenize = base; break; }
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
function inComment(stream, state) {
|
||||
var next, last;
|
||||
while (next = stream.next()) {
|
||||
if (next == "#" && last == "|") { state.tokenize = base; break; }
|
||||
last = next;
|
||||
}
|
||||
type = "ws";
|
||||
return "comment";
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function () {
|
||||
return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base};
|
||||
},
|
||||
|
||||
token: function (stream, state) {
|
||||
if (stream.sol() && typeof state.ctx.indentTo != "number")
|
||||
state.ctx.indentTo = state.ctx.start + 1;
|
||||
|
||||
type = null;
|
||||
var style = state.tokenize(stream, state);
|
||||
if (type != "ws") {
|
||||
if (state.ctx.indentTo == null) {
|
||||
if (type == "symbol" && assumeBody.test(stream.current()))
|
||||
state.ctx.indentTo = state.ctx.start + config.indentUnit;
|
||||
else
|
||||
state.ctx.indentTo = "next";
|
||||
} else if (state.ctx.indentTo == "next") {
|
||||
state.ctx.indentTo = stream.column();
|
||||
}
|
||||
state.lastType = type;
|
||||
}
|
||||
if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};
|
||||
else if (type == "close") state.ctx = state.ctx.prev || state.ctx;
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function (state, _textAfter) {
|
||||
var i = state.ctx.indentTo;
|
||||
return typeof i == "number" ? i : state.ctx.start + 1;
|
||||
},
|
||||
|
||||
closeBrackets: {pairs: "()[]{}\"\""},
|
||||
lineComment: ";;",
|
||||
blockCommentStart: "#|",
|
||||
blockCommentEnd: "|#"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");
|
||||
|
||||
});
|
||||
@@ -0,0 +1,177 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Common Lisp mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="commonlisp.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Common Lisp</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Common Lisp mode</h2>
|
||||
<form><textarea id="code" name="code">(in-package :cl-postgres)
|
||||
|
||||
;; These are used to synthesize reader and writer names for integer
|
||||
;; reading/writing functions when the amount of bytes and the
|
||||
;; signedness is known. Both the macro that creates the functions and
|
||||
;; some macros that use them create names this way.
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(defun integer-reader-name (bytes signed)
|
||||
(intern (with-standard-io-syntax
|
||||
(format nil "~a~a~a~a" '#:read- (if signed "" '#:u) '#:int bytes))))
|
||||
(defun integer-writer-name (bytes signed)
|
||||
(intern (with-standard-io-syntax
|
||||
(format nil "~a~a~a~a" '#:write- (if signed "" '#:u) '#:int bytes)))))
|
||||
|
||||
(defmacro integer-reader (bytes)
|
||||
"Create a function to read integers from a binary stream."
|
||||
(let ((bits (* bytes 8)))
|
||||
(labels ((return-form (signed)
|
||||
(if signed
|
||||
`(if (logbitp ,(1- bits) result)
|
||||
(dpb result (byte ,(1- bits) 0) -1)
|
||||
result)
|
||||
`result))
|
||||
(generate-reader (signed)
|
||||
`(defun ,(integer-reader-name bytes signed) (socket)
|
||||
(declare (type stream socket)
|
||||
#.*optimize*)
|
||||
,(if (= bytes 1)
|
||||
`(let ((result (the (unsigned-byte 8) (read-byte socket))))
|
||||
(declare (type (unsigned-byte 8) result))
|
||||
,(return-form signed))
|
||||
`(let ((result 0))
|
||||
(declare (type (unsigned-byte ,bits) result))
|
||||
,@(loop :for byte :from (1- bytes) :downto 0
|
||||
:collect `(setf (ldb (byte 8 ,(* 8 byte)) result)
|
||||
(the (unsigned-byte 8) (read-byte socket))))
|
||||
,(return-form signed))))))
|
||||
`(progn
|
||||
;; This causes weird errors on SBCL in some circumstances. Disabled for now.
|
||||
;; (declaim (inline ,(integer-reader-name bytes t)
|
||||
;; ,(integer-reader-name bytes nil)))
|
||||
(declaim (ftype (function (t) (signed-byte ,bits))
|
||||
,(integer-reader-name bytes t)))
|
||||
,(generate-reader t)
|
||||
(declaim (ftype (function (t) (unsigned-byte ,bits))
|
||||
,(integer-reader-name bytes nil)))
|
||||
,(generate-reader nil)))))
|
||||
|
||||
(defmacro integer-writer (bytes)
|
||||
"Create a function to write integers to a binary stream."
|
||||
(let ((bits (* 8 bytes)))
|
||||
`(progn
|
||||
(declaim (inline ,(integer-writer-name bytes t)
|
||||
,(integer-writer-name bytes nil)))
|
||||
(defun ,(integer-writer-name bytes nil) (socket value)
|
||||
(declare (type stream socket)
|
||||
(type (unsigned-byte ,bits) value)
|
||||
#.*optimize*)
|
||||
,@(if (= bytes 1)
|
||||
`((write-byte value socket))
|
||||
(loop :for byte :from (1- bytes) :downto 0
|
||||
:collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)
|
||||
socket)))
|
||||
(values))
|
||||
(defun ,(integer-writer-name bytes t) (socket value)
|
||||
(declare (type stream socket)
|
||||
(type (signed-byte ,bits) value)
|
||||
#.*optimize*)
|
||||
,@(if (= bytes 1)
|
||||
`((write-byte (ldb (byte 8 0) value) socket))
|
||||
(loop :for byte :from (1- bytes) :downto 0
|
||||
:collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)
|
||||
socket)))
|
||||
(values)))))
|
||||
|
||||
;; All the instances of the above that we need.
|
||||
|
||||
(integer-reader 1)
|
||||
(integer-reader 2)
|
||||
(integer-reader 4)
|
||||
(integer-reader 8)
|
||||
|
||||
(integer-writer 1)
|
||||
(integer-writer 2)
|
||||
(integer-writer 4)
|
||||
|
||||
(defun write-bytes (socket bytes)
|
||||
"Write a byte-array to a stream."
|
||||
(declare (type stream socket)
|
||||
(type (simple-array (unsigned-byte 8)) bytes)
|
||||
#.*optimize*)
|
||||
(write-sequence bytes socket))
|
||||
|
||||
(defun write-str (socket string)
|
||||
"Write a null-terminated string to a stream \(encoding it when UTF-8
|
||||
support is enabled.)."
|
||||
(declare (type stream socket)
|
||||
(type string string)
|
||||
#.*optimize*)
|
||||
(enc-write-string string socket)
|
||||
(write-uint1 socket 0))
|
||||
|
||||
(declaim (ftype (function (t unsigned-byte)
|
||||
(simple-array (unsigned-byte 8) (*)))
|
||||
read-bytes))
|
||||
(defun read-bytes (socket length)
|
||||
"Read a byte array of the given length from a stream."
|
||||
(declare (type stream socket)
|
||||
(type fixnum length)
|
||||
#.*optimize*)
|
||||
(let ((result (make-array length :element-type '(unsigned-byte 8))))
|
||||
(read-sequence result socket)
|
||||
result))
|
||||
|
||||
(declaim (ftype (function (t) string) read-str))
|
||||
(defun read-str (socket)
|
||||
"Read a null-terminated string from a stream. Takes care of encoding
|
||||
when UTF-8 support is enabled."
|
||||
(declare (type stream socket)
|
||||
#.*optimize*)
|
||||
(enc-read-string socket :null-terminated t))
|
||||
|
||||
(defun skip-bytes (socket length)
|
||||
"Skip a given number of bytes in a binary stream."
|
||||
(declare (type stream socket)
|
||||
(type (unsigned-byte 32) length)
|
||||
#.*optimize*)
|
||||
(dotimes (i length)
|
||||
(read-byte socket)))
|
||||
|
||||
(defun skip-str (socket)
|
||||
"Skip a null-terminated string."
|
||||
(declare (type stream socket)
|
||||
#.*optimize*)
|
||||
(loop :for char :of-type fixnum = (read-byte socket)
|
||||
:until (zerop char)))
|
||||
|
||||
(defun ensure-socket-is-closed (socket &key abort)
|
||||
(when (open-stream-p socket)
|
||||
(handler-case
|
||||
(close socket :abort abort)
|
||||
(error (error)
|
||||
(warn "Ignoring the error which happened while trying to close PostgreSQL socket: ~A" error)))))
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {lineNumbers: true});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-common-lisp</code>.</p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,391 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("crystal", function(config) {
|
||||
function wordRegExp(words, end) {
|
||||
return new RegExp((end ? "" : "^") + "(?:" + words.join("|") + ")" + (end ? "$" : "\\b"));
|
||||
}
|
||||
|
||||
function chain(tokenize, stream, state) {
|
||||
state.tokenize.push(tokenize);
|
||||
return tokenize(stream, state);
|
||||
}
|
||||
|
||||
var operators = /^(?:[-+/%|&^]|\*\*?|[<>]{2})/;
|
||||
var conditionalOperators = /^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/;
|
||||
var indexingOperators = /^(?:\[\][?=]?)/;
|
||||
var anotherOperators = /^(?:\.(?:\.{2})?|->|[?:])/;
|
||||
var idents = /^[a-z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/;
|
||||
var types = /^[A-Z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/;
|
||||
var keywords = wordRegExp([
|
||||
"abstract", "alias", "as", "asm", "begin", "break", "case", "class", "def", "do",
|
||||
"else", "elsif", "end", "ensure", "enum", "extend", "for", "fun", "if", "ifdef",
|
||||
"include", "instance_sizeof", "lib", "macro", "module", "next", "of", "out", "pointerof",
|
||||
"private", "protected", "rescue", "return", "require", "sizeof", "struct",
|
||||
"super", "then", "type", "typeof", "union", "unless", "until", "when", "while", "with",
|
||||
"yield", "__DIR__", "__FILE__", "__LINE__"
|
||||
]);
|
||||
var atomWords = wordRegExp(["true", "false", "nil", "self"]);
|
||||
var indentKeywordsArray = [
|
||||
"def", "fun", "macro",
|
||||
"class", "module", "struct", "lib", "enum", "union",
|
||||
"if", "unless", "case", "while", "until", "begin", "then",
|
||||
"do",
|
||||
"for", "ifdef"
|
||||
];
|
||||
var indentKeywords = wordRegExp(indentKeywordsArray);
|
||||
var dedentKeywordsArray = [
|
||||
"end",
|
||||
"else", "elsif",
|
||||
"rescue", "ensure"
|
||||
];
|
||||
var dedentKeywords = wordRegExp(dedentKeywordsArray);
|
||||
var dedentPunctualsArray = ["\\)", "\\}", "\\]"];
|
||||
var dedentPunctuals = new RegExp("^(?:" + dedentPunctualsArray.join("|") + ")$");
|
||||
var nextTokenizer = {
|
||||
"def": tokenFollowIdent, "fun": tokenFollowIdent, "macro": tokenMacroDef,
|
||||
"class": tokenFollowType, "module": tokenFollowType, "struct": tokenFollowType,
|
||||
"lib": tokenFollowType, "enum": tokenFollowType, "union": tokenFollowType
|
||||
};
|
||||
var matching = {"[": "]", "{": "}", "(": ")", "<": ">"};
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Macros
|
||||
if (state.lastToken != "\\" && stream.match("{%", false)) {
|
||||
return chain(tokenMacro("%", "%"), stream, state);
|
||||
}
|
||||
|
||||
if (state.lastToken != "\\" && stream.match("{{", false)) {
|
||||
return chain(tokenMacro("{", "}"), stream, state);
|
||||
}
|
||||
|
||||
// Comments
|
||||
if (stream.peek() == "#") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
|
||||
// Variables and keywords
|
||||
var matched;
|
||||
if (stream.match(idents)) {
|
||||
stream.eat(/[?!]/);
|
||||
|
||||
matched = stream.current();
|
||||
if (stream.eat(":")) {
|
||||
return "atom";
|
||||
} else if (state.lastToken == ".") {
|
||||
return "property";
|
||||
} else if (keywords.test(matched)) {
|
||||
if (state.lastToken != "abstract" && indentKeywords.test(matched)) {
|
||||
if (!(matched == "fun" && state.blocks.indexOf("lib") >= 0)) {
|
||||
state.blocks.push(matched);
|
||||
state.currentIndent += 1;
|
||||
}
|
||||
} else if (dedentKeywords.test(matched)) {
|
||||
state.blocks.pop();
|
||||
state.currentIndent -= 1;
|
||||
}
|
||||
|
||||
if (nextTokenizer.hasOwnProperty(matched)) {
|
||||
state.tokenize.push(nextTokenizer[matched]);
|
||||
}
|
||||
|
||||
return "keyword";
|
||||
} else if (atomWords.test(matched)) {
|
||||
return "atom";
|
||||
}
|
||||
|
||||
return "variable";
|
||||
}
|
||||
|
||||
// Class variables and instance variables
|
||||
// or attributes
|
||||
if (stream.eat("@")) {
|
||||
if (stream.peek() == "[") {
|
||||
return chain(tokenNest("[", "]", "meta"), stream, state);
|
||||
}
|
||||
|
||||
stream.eat("@");
|
||||
stream.match(idents) || stream.match(types);
|
||||
return "variable-2";
|
||||
}
|
||||
|
||||
// Global variables
|
||||
if (stream.eat("$")) {
|
||||
stream.eat(/[0-9]+|\?/) || stream.match(idents) || stream.match(types);
|
||||
return "variable-3";
|
||||
}
|
||||
|
||||
// Constants and types
|
||||
if (stream.match(types)) {
|
||||
return "tag";
|
||||
}
|
||||
|
||||
// Symbols or ':' operator
|
||||
if (stream.eat(":")) {
|
||||
if (stream.eat("\"")) {
|
||||
return chain(tokenQuote("\"", "atom", false), stream, state);
|
||||
} else if (stream.match(idents) || stream.match(types) ||
|
||||
stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators)) {
|
||||
return "atom";
|
||||
}
|
||||
stream.eat(":");
|
||||
return "operator";
|
||||
}
|
||||
|
||||
// Strings
|
||||
if (stream.eat("\"")) {
|
||||
return chain(tokenQuote("\"", "string", true), stream, state);
|
||||
}
|
||||
|
||||
// Strings or regexps or macro variables or '%' operator
|
||||
if (stream.peek() == "%") {
|
||||
var style = "string";
|
||||
var embed = true;
|
||||
var delim;
|
||||
|
||||
if (stream.match("%r")) {
|
||||
// Regexps
|
||||
style = "string-2";
|
||||
delim = stream.next();
|
||||
} else if (stream.match("%w")) {
|
||||
embed = false;
|
||||
delim = stream.next();
|
||||
} else {
|
||||
if(delim = stream.match(/^%([^\w\s=])/)) {
|
||||
delim = delim[1];
|
||||
} else if (stream.match(/^%[a-zA-Z0-9_\u009F-\uFFFF]*/)) {
|
||||
// Macro variables
|
||||
return "meta";
|
||||
} else {
|
||||
// '%' operator
|
||||
return "operator";
|
||||
}
|
||||
}
|
||||
|
||||
if (matching.hasOwnProperty(delim)) {
|
||||
delim = matching[delim];
|
||||
}
|
||||
return chain(tokenQuote(delim, style, embed), stream, state);
|
||||
}
|
||||
|
||||
// Characters
|
||||
if (stream.eat("'")) {
|
||||
stream.match(/^(?:[^']|\\(?:[befnrtv0'"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\{[0-9a-fA-F]{1,6}\})))/);
|
||||
stream.eat("'");
|
||||
return "atom";
|
||||
}
|
||||
|
||||
// Numbers
|
||||
if (stream.eat("0")) {
|
||||
if (stream.eat("x")) {
|
||||
stream.match(/^[0-9a-fA-F]+/);
|
||||
} else if (stream.eat("o")) {
|
||||
stream.match(/^[0-7]+/);
|
||||
} else if (stream.eat("b")) {
|
||||
stream.match(/^[01]+/);
|
||||
}
|
||||
return "number";
|
||||
}
|
||||
|
||||
if (stream.eat(/\d/)) {
|
||||
stream.match(/^\d*(?:\.\d+)?(?:[eE][+-]?\d+)?/);
|
||||
return "number";
|
||||
}
|
||||
|
||||
// Operators
|
||||
if (stream.match(operators)) {
|
||||
stream.eat("="); // Operators can follow assign symbol.
|
||||
return "operator";
|
||||
}
|
||||
|
||||
if (stream.match(conditionalOperators) || stream.match(anotherOperators)) {
|
||||
return "operator";
|
||||
}
|
||||
|
||||
// Parens and braces
|
||||
if (matched = stream.match(/[({[]/, false)) {
|
||||
matched = matched[0];
|
||||
return chain(tokenNest(matched, matching[matched], null), stream, state);
|
||||
}
|
||||
|
||||
// Escapes
|
||||
if (stream.eat("\\")) {
|
||||
stream.next();
|
||||
return "meta";
|
||||
}
|
||||
|
||||
stream.next();
|
||||
return null;
|
||||
}
|
||||
|
||||
function tokenNest(begin, end, style, started) {
|
||||
return function (stream, state) {
|
||||
if (!started && stream.match(begin)) {
|
||||
state.tokenize[state.tokenize.length - 1] = tokenNest(begin, end, style, true);
|
||||
state.currentIndent += 1;
|
||||
return style;
|
||||
}
|
||||
|
||||
var nextStyle = tokenBase(stream, state);
|
||||
if (stream.current() === end) {
|
||||
state.tokenize.pop();
|
||||
state.currentIndent -= 1;
|
||||
nextStyle = style;
|
||||
}
|
||||
|
||||
return nextStyle;
|
||||
};
|
||||
}
|
||||
|
||||
function tokenMacro(begin, end, started) {
|
||||
return function (stream, state) {
|
||||
if (!started && stream.match("{" + begin)) {
|
||||
state.currentIndent += 1;
|
||||
state.tokenize[state.tokenize.length - 1] = tokenMacro(begin, end, true);
|
||||
return "meta";
|
||||
}
|
||||
|
||||
if (stream.match(end + "}")) {
|
||||
state.currentIndent -= 1;
|
||||
state.tokenize.pop();
|
||||
return "meta";
|
||||
}
|
||||
|
||||
return tokenBase(stream, state);
|
||||
};
|
||||
}
|
||||
|
||||
function tokenMacroDef(stream, state) {
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var matched;
|
||||
if (matched = stream.match(idents)) {
|
||||
if (matched == "def") {
|
||||
return "keyword";
|
||||
}
|
||||
stream.eat(/[?!]/);
|
||||
}
|
||||
|
||||
state.tokenize.pop();
|
||||
return "def";
|
||||
}
|
||||
|
||||
function tokenFollowIdent(stream, state) {
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (stream.match(idents)) {
|
||||
stream.eat(/[!?]/);
|
||||
} else {
|
||||
stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators);
|
||||
}
|
||||
state.tokenize.pop();
|
||||
return "def";
|
||||
}
|
||||
|
||||
function tokenFollowType(stream, state) {
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
stream.match(types);
|
||||
state.tokenize.pop();
|
||||
return "def";
|
||||
}
|
||||
|
||||
function tokenQuote(end, style, embed) {
|
||||
return function (stream, state) {
|
||||
var escaped = false;
|
||||
|
||||
while (stream.peek()) {
|
||||
if (!escaped) {
|
||||
if (stream.match("{%", false)) {
|
||||
state.tokenize.push(tokenMacro("%", "%"));
|
||||
return style;
|
||||
}
|
||||
|
||||
if (stream.match("{{", false)) {
|
||||
state.tokenize.push(tokenMacro("{", "}"));
|
||||
return style;
|
||||
}
|
||||
|
||||
if (embed && stream.match("#{", false)) {
|
||||
state.tokenize.push(tokenNest("#{", "}", "meta"));
|
||||
return style;
|
||||
}
|
||||
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch == end) {
|
||||
state.tokenize.pop();
|
||||
return style;
|
||||
}
|
||||
|
||||
escaped = ch == "\\";
|
||||
} else {
|
||||
stream.next();
|
||||
escaped = false;
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function () {
|
||||
return {
|
||||
tokenize: [tokenBase],
|
||||
currentIndent: 0,
|
||||
lastToken: null,
|
||||
blocks: []
|
||||
};
|
||||
},
|
||||
|
||||
token: function (stream, state) {
|
||||
var style = state.tokenize[state.tokenize.length - 1](stream, state);
|
||||
var token = stream.current();
|
||||
|
||||
if (style && style != "comment") {
|
||||
state.lastToken = token;
|
||||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function (state, textAfter) {
|
||||
textAfter = textAfter.replace(/^\s*(?:\{%)?\s*|\s*(?:%\})?\s*$/g, "");
|
||||
|
||||
if (dedentKeywords.test(textAfter) || dedentPunctuals.test(textAfter)) {
|
||||
return config.indentUnit * (state.currentIndent - 1);
|
||||
}
|
||||
|
||||
return config.indentUnit * state.currentIndent;
|
||||
},
|
||||
|
||||
fold: "indent",
|
||||
electricInput: wordRegExp(dedentPunctualsArray.concat(dedentKeywordsArray), true),
|
||||
lineComment: '#'
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-crystal", "crystal");
|
||||
});
|
||||
@@ -0,0 +1,119 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Crystal mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="crystal.js"></script>
|
||||
<style>
|
||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
||||
.cm-s-default span.cm-arrow { color: red; }
|
||||
</style>
|
||||
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Crystal</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Crystal mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
# Features of Crystal
|
||||
# - Ruby-inspired syntax.
|
||||
# - Statically type-checked but without having to specify the type of variables or method arguments.
|
||||
# - Be able to call C code by writing bindings to it in Crystal.
|
||||
# - Have compile-time evaluation and generation of code, to avoid boilerplate code.
|
||||
# - Compile to efficient native code.
|
||||
|
||||
# A very basic HTTP server
|
||||
require "http/server"
|
||||
|
||||
server = HTTP::Server.new(8080) do |request|
|
||||
HTTP::Response.ok "text/plain", "Hello world, got #{request.path}!"
|
||||
end
|
||||
|
||||
puts "Listening on http://0.0.0.0:8080"
|
||||
server.listen
|
||||
|
||||
module Foo
|
||||
def initialize(@foo); end
|
||||
|
||||
abstract def abstract_method : String
|
||||
|
||||
@[AlwaysInline]
|
||||
def with_foofoo
|
||||
with Foo.new(self) yield
|
||||
end
|
||||
|
||||
struct Foo
|
||||
def initialize(@foo); end
|
||||
|
||||
def hello_world
|
||||
@foo.abstract_method
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Bar
|
||||
include Foo
|
||||
|
||||
@@foobar = 12345
|
||||
|
||||
def initialize(@bar)
|
||||
super(@bar.not_nil! + 100)
|
||||
end
|
||||
|
||||
macro alias_method(name, method)
|
||||
def {{ name }}(*args)
|
||||
{{ method }}(*args)
|
||||
end
|
||||
end
|
||||
|
||||
def a_method
|
||||
"Hello, World"
|
||||
end
|
||||
|
||||
alias_method abstract_method, a_method
|
||||
|
||||
macro def show_instance_vars : Nil
|
||||
{% for var in @type.instance_vars %}
|
||||
puts "@{{ var }} = #{ @{{ var }} }"
|
||||
{% end %}
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
class Baz < Bar; end
|
||||
|
||||
lib LibC
|
||||
fun c_puts = "puts"(str : Char*) : Int
|
||||
end
|
||||
|
||||
$baz = Baz.new(100)
|
||||
$baz.show_instance_vars
|
||||
$baz.with_foofoo do
|
||||
LibC.c_puts hello_world
|
||||
end
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: "text/x-crystal",
|
||||
matchBrackets: true,
|
||||
indentUnit: 2
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-crystal</code>.</p>
|
||||
</article>
|
||||
@@ -0,0 +1,825 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("css", function(config, parserConfig) {
|
||||
var inline = parserConfig.inline
|
||||
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
|
||||
|
||||
var indentUnit = config.indentUnit,
|
||||
tokenHooks = parserConfig.tokenHooks,
|
||||
documentTypes = parserConfig.documentTypes || {},
|
||||
mediaTypes = parserConfig.mediaTypes || {},
|
||||
mediaFeatures = parserConfig.mediaFeatures || {},
|
||||
mediaValueKeywords = parserConfig.mediaValueKeywords || {},
|
||||
propertyKeywords = parserConfig.propertyKeywords || {},
|
||||
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
|
||||
fontProperties = parserConfig.fontProperties || {},
|
||||
counterDescriptors = parserConfig.counterDescriptors || {},
|
||||
colorKeywords = parserConfig.colorKeywords || {},
|
||||
valueKeywords = parserConfig.valueKeywords || {},
|
||||
allowNested = parserConfig.allowNested,
|
||||
supportsAtComponent = parserConfig.supportsAtComponent === true;
|
||||
|
||||
var type, override;
|
||||
function ret(style, tp) { type = tp; return style; }
|
||||
|
||||
// Tokenizers
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (tokenHooks[ch]) {
|
||||
var result = tokenHooks[ch](stream, state);
|
||||
if (result !== false) return result;
|
||||
}
|
||||
if (ch == "@") {
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
return ret("def", stream.current());
|
||||
} else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
|
||||
return ret(null, "compare");
|
||||
} else if (ch == "\"" || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
} else if (ch == "#") {
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
return ret("atom", "hash");
|
||||
} else if (ch == "!") {
|
||||
stream.match(/^\s*\w*/);
|
||||
return ret("keyword", "important");
|
||||
} else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
|
||||
stream.eatWhile(/[\w.%]/);
|
||||
return ret("number", "unit");
|
||||
} else if (ch === "-") {
|
||||
if (/[\d.]/.test(stream.peek())) {
|
||||
stream.eatWhile(/[\w.%]/);
|
||||
return ret("number", "unit");
|
||||
} else if (stream.match(/^-[\w\\\-]+/)) {
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
if (stream.match(/^\s*:/, false))
|
||||
return ret("variable-2", "variable-definition");
|
||||
return ret("variable-2", "variable");
|
||||
} else if (stream.match(/^\w+-/)) {
|
||||
return ret("meta", "meta");
|
||||
}
|
||||
} else if (/[,+>*\/]/.test(ch)) {
|
||||
return ret(null, "select-op");
|
||||
} else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
|
||||
return ret("qualifier", "qualifier");
|
||||
} else if (/[:;{}\[\]\(\)]/.test(ch)) {
|
||||
return ret(null, ch);
|
||||
} else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
|
||||
(ch == "d" && stream.match("omain(")) ||
|
||||
(ch == "r" && stream.match("egexp("))) {
|
||||
stream.backUp(1);
|
||||
state.tokenize = tokenParenthesized;
|
||||
return ret("property", "word");
|
||||
} else if (/[\w\\\-]/.test(ch)) {
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
return ret("property", "word");
|
||||
} else {
|
||||
return ret(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, ch;
|
||||
while ((ch = stream.next()) != null) {
|
||||
if (ch == quote && !escaped) {
|
||||
if (quote == ")") stream.backUp(1);
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && ch == "\\";
|
||||
}
|
||||
if (ch == quote || !escaped && quote != ")") state.tokenize = null;
|
||||
return ret("string", "string");
|
||||
};
|
||||
}
|
||||
|
||||
function tokenParenthesized(stream, state) {
|
||||
stream.next(); // Must be '('
|
||||
if (!stream.match(/\s*[\"\')]/, false))
|
||||
state.tokenize = tokenString(")");
|
||||
else
|
||||
state.tokenize = null;
|
||||
return ret(null, "(");
|
||||
}
|
||||
|
||||
// Context management
|
||||
|
||||
function Context(type, indent, prev) {
|
||||
this.type = type;
|
||||
this.indent = indent;
|
||||
this.prev = prev;
|
||||
}
|
||||
|
||||
function pushContext(state, stream, type, indent) {
|
||||
state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
|
||||
return type;
|
||||
}
|
||||
|
||||
function popContext(state) {
|
||||
if (state.context.prev)
|
||||
state.context = state.context.prev;
|
||||
return state.context.type;
|
||||
}
|
||||
|
||||
function pass(type, stream, state) {
|
||||
return states[state.context.type](type, stream, state);
|
||||
}
|
||||
function popAndPass(type, stream, state, n) {
|
||||
for (var i = n || 1; i > 0; i--)
|
||||
state.context = state.context.prev;
|
||||
return pass(type, stream, state);
|
||||
}
|
||||
|
||||
// Parser
|
||||
|
||||
function wordAsValue(stream) {
|
||||
var word = stream.current().toLowerCase();
|
||||
if (valueKeywords.hasOwnProperty(word))
|
||||
override = "atom";
|
||||
else if (colorKeywords.hasOwnProperty(word))
|
||||
override = "keyword";
|
||||
else
|
||||
override = "variable";
|
||||
}
|
||||
|
||||
var states = {};
|
||||
|
||||
states.top = function(type, stream, state) {
|
||||
if (type == "{") {
|
||||
return pushContext(state, stream, "block");
|
||||
} else if (type == "}" && state.context.prev) {
|
||||
return popContext(state);
|
||||
} else if (supportsAtComponent && /@component/.test(type)) {
|
||||
return pushContext(state, stream, "atComponentBlock");
|
||||
} else if (/^@(-moz-)?document$/.test(type)) {
|
||||
return pushContext(state, stream, "documentTypes");
|
||||
} else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) {
|
||||
return pushContext(state, stream, "atBlock");
|
||||
} else if (/^@(font-face|counter-style)/.test(type)) {
|
||||
state.stateArg = type;
|
||||
return "restricted_atBlock_before";
|
||||
} else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
|
||||
return "keyframes";
|
||||
} else if (type && type.charAt(0) == "@") {
|
||||
return pushContext(state, stream, "at");
|
||||
} else if (type == "hash") {
|
||||
override = "builtin";
|
||||
} else if (type == "word") {
|
||||
override = "tag";
|
||||
} else if (type == "variable-definition") {
|
||||
return "maybeprop";
|
||||
} else if (type == "interpolation") {
|
||||
return pushContext(state, stream, "interpolation");
|
||||
} else if (type == ":") {
|
||||
return "pseudo";
|
||||
} else if (allowNested && type == "(") {
|
||||
return pushContext(state, stream, "parens");
|
||||
}
|
||||
return state.context.type;
|
||||
};
|
||||
|
||||
states.block = function(type, stream, state) {
|
||||
if (type == "word") {
|
||||
var word = stream.current().toLowerCase();
|
||||
if (propertyKeywords.hasOwnProperty(word)) {
|
||||
override = "property";
|
||||
return "maybeprop";
|
||||
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
|
||||
override = "string-2";
|
||||
return "maybeprop";
|
||||
} else if (allowNested) {
|
||||
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
|
||||
return "block";
|
||||
} else {
|
||||
override += " error";
|
||||
return "maybeprop";
|
||||
}
|
||||
} else if (type == "meta") {
|
||||
return "block";
|
||||
} else if (!allowNested && (type == "hash" || type == "qualifier")) {
|
||||
override = "error";
|
||||
return "block";
|
||||
} else {
|
||||
return states.top(type, stream, state);
|
||||
}
|
||||
};
|
||||
|
||||
states.maybeprop = function(type, stream, state) {
|
||||
if (type == ":") return pushContext(state, stream, "prop");
|
||||
return pass(type, stream, state);
|
||||
};
|
||||
|
||||
states.prop = function(type, stream, state) {
|
||||
if (type == ";") return popContext(state);
|
||||
if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
|
||||
if (type == "}" || type == "{") return popAndPass(type, stream, state);
|
||||
if (type == "(") return pushContext(state, stream, "parens");
|
||||
|
||||
if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) {
|
||||
override += " error";
|
||||
} else if (type == "word") {
|
||||
wordAsValue(stream);
|
||||
} else if (type == "interpolation") {
|
||||
return pushContext(state, stream, "interpolation");
|
||||
}
|
||||
return "prop";
|
||||
};
|
||||
|
||||
states.propBlock = function(type, _stream, state) {
|
||||
if (type == "}") return popContext(state);
|
||||
if (type == "word") { override = "property"; return "maybeprop"; }
|
||||
return state.context.type;
|
||||
};
|
||||
|
||||
states.parens = function(type, stream, state) {
|
||||
if (type == "{" || type == "}") return popAndPass(type, stream, state);
|
||||
if (type == ")") return popContext(state);
|
||||
if (type == "(") return pushContext(state, stream, "parens");
|
||||
if (type == "interpolation") return pushContext(state, stream, "interpolation");
|
||||
if (type == "word") wordAsValue(stream);
|
||||
return "parens";
|
||||
};
|
||||
|
||||
states.pseudo = function(type, stream, state) {
|
||||
if (type == "word") {
|
||||
override = "variable-3";
|
||||
return state.context.type;
|
||||
}
|
||||
return pass(type, stream, state);
|
||||
};
|
||||
|
||||
states.documentTypes = function(type, stream, state) {
|
||||
if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
|
||||
override = "tag";
|
||||
return state.context.type;
|
||||
} else {
|
||||
return states.atBlock(type, stream, state);
|
||||
}
|
||||
};
|
||||
|
||||
states.atBlock = function(type, stream, state) {
|
||||
if (type == "(") return pushContext(state, stream, "atBlock_parens");
|
||||
if (type == "}" || type == ";") return popAndPass(type, stream, state);
|
||||
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
|
||||
|
||||
if (type == "interpolation") return pushContext(state, stream, "interpolation");
|
||||
|
||||
if (type == "word") {
|
||||
var word = stream.current().toLowerCase();
|
||||
if (word == "only" || word == "not" || word == "and" || word == "or")
|
||||
override = "keyword";
|
||||
else if (mediaTypes.hasOwnProperty(word))
|
||||
override = "attribute";
|
||||
else if (mediaFeatures.hasOwnProperty(word))
|
||||
override = "property";
|
||||
else if (mediaValueKeywords.hasOwnProperty(word))
|
||||
override = "keyword";
|
||||
else if (propertyKeywords.hasOwnProperty(word))
|
||||
override = "property";
|
||||
else if (nonStandardPropertyKeywords.hasOwnProperty(word))
|
||||
override = "string-2";
|
||||
else if (valueKeywords.hasOwnProperty(word))
|
||||
override = "atom";
|
||||
else if (colorKeywords.hasOwnProperty(word))
|
||||
override = "keyword";
|
||||
else
|
||||
override = "error";
|
||||
}
|
||||
return state.context.type;
|
||||
};
|
||||
|
||||
states.atComponentBlock = function(type, stream, state) {
|
||||
if (type == "}")
|
||||
return popAndPass(type, stream, state);
|
||||
if (type == "{")
|
||||
return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
|
||||
if (type == "word")
|
||||
override = "error";
|
||||
return state.context.type;
|
||||
};
|
||||
|
||||
states.atBlock_parens = function(type, stream, state) {
|
||||
if (type == ")") return popContext(state);
|
||||
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
|
||||
return states.atBlock(type, stream, state);
|
||||
};
|
||||
|
||||
states.restricted_atBlock_before = function(type, stream, state) {
|
||||
if (type == "{")
|
||||
return pushContext(state, stream, "restricted_atBlock");
|
||||
if (type == "word" && state.stateArg == "@counter-style") {
|
||||
override = "variable";
|
||||
return "restricted_atBlock_before";
|
||||
}
|
||||
return pass(type, stream, state);
|
||||
};
|
||||
|
||||
states.restricted_atBlock = function(type, stream, state) {
|
||||
if (type == "}") {
|
||||
state.stateArg = null;
|
||||
return popContext(state);
|
||||
}
|
||||
if (type == "word") {
|
||||
if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
|
||||
(state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
|
||||
override = "error";
|
||||
else
|
||||
override = "property";
|
||||
return "maybeprop";
|
||||
}
|
||||
return "restricted_atBlock";
|
||||
};
|
||||
|
||||
states.keyframes = function(type, stream, state) {
|
||||
if (type == "word") { override = "variable"; return "keyframes"; }
|
||||
if (type == "{") return pushContext(state, stream, "top");
|
||||
return pass(type, stream, state);
|
||||
};
|
||||
|
||||
states.at = function(type, stream, state) {
|
||||
if (type == ";") return popContext(state);
|
||||
if (type == "{" || type == "}") return popAndPass(type, stream, state);
|
||||
if (type == "word") override = "tag";
|
||||
else if (type == "hash") override = "builtin";
|
||||
return "at";
|
||||
};
|
||||
|
||||
states.interpolation = function(type, stream, state) {
|
||||
if (type == "}") return popContext(state);
|
||||
if (type == "{" || type == ";") return popAndPass(type, stream, state);
|
||||
if (type == "word") override = "variable";
|
||||
else if (type != "variable" && type != "(" && type != ")") override = "error";
|
||||
return "interpolation";
|
||||
};
|
||||
|
||||
return {
|
||||
startState: function(base) {
|
||||
return {tokenize: null,
|
||||
state: inline ? "block" : "top",
|
||||
stateArg: null,
|
||||
context: new Context(inline ? "block" : "top", base || 0, null)};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (!state.tokenize && stream.eatSpace()) return null;
|
||||
var style = (state.tokenize || tokenBase)(stream, state);
|
||||
if (style && typeof style == "object") {
|
||||
type = style[1];
|
||||
style = style[0];
|
||||
}
|
||||
override = style;
|
||||
state.state = states[state.state](type, stream, state);
|
||||
return override;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
var cx = state.context, ch = textAfter && textAfter.charAt(0);
|
||||
var indent = cx.indent;
|
||||
if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
|
||||
if (cx.prev) {
|
||||
if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
|
||||
cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
|
||||
// Resume indentation from parent context.
|
||||
cx = cx.prev;
|
||||
indent = cx.indent;
|
||||
} else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
|
||||
ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
|
||||
// Dedent relative to current context.
|
||||
indent = Math.max(0, cx.indent - indentUnit);
|
||||
cx = cx.prev;
|
||||
}
|
||||
}
|
||||
return indent;
|
||||
},
|
||||
|
||||
electricChars: "}",
|
||||
blockCommentStart: "/*",
|
||||
blockCommentEnd: "*/",
|
||||
fold: "brace"
|
||||
};
|
||||
});
|
||||
|
||||
function keySet(array) {
|
||||
var keys = {};
|
||||
for (var i = 0; i < array.length; ++i) {
|
||||
keys[array[i]] = true;
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
var documentTypes_ = [
|
||||
"domain", "regexp", "url", "url-prefix"
|
||||
], documentTypes = keySet(documentTypes_);
|
||||
|
||||
var mediaTypes_ = [
|
||||
"all", "aural", "braille", "handheld", "print", "projection", "screen",
|
||||
"tty", "tv", "embossed"
|
||||
], mediaTypes = keySet(mediaTypes_);
|
||||
|
||||
var mediaFeatures_ = [
|
||||
"width", "min-width", "max-width", "height", "min-height", "max-height",
|
||||
"device-width", "min-device-width", "max-device-width", "device-height",
|
||||
"min-device-height", "max-device-height", "aspect-ratio",
|
||||
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
|
||||
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
|
||||
"max-color", "color-index", "min-color-index", "max-color-index",
|
||||
"monochrome", "min-monochrome", "max-monochrome", "resolution",
|
||||
"min-resolution", "max-resolution", "scan", "grid", "orientation",
|
||||
"device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
|
||||
"pointer", "any-pointer", "hover", "any-hover"
|
||||
], mediaFeatures = keySet(mediaFeatures_);
|
||||
|
||||
var mediaValueKeywords_ = [
|
||||
"landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
|
||||
"interlace", "progressive"
|
||||
], mediaValueKeywords = keySet(mediaValueKeywords_);
|
||||
|
||||
var propertyKeywords_ = [
|
||||
"align-content", "align-items", "align-self", "alignment-adjust",
|
||||
"alignment-baseline", "anchor-point", "animation", "animation-delay",
|
||||
"animation-direction", "animation-duration", "animation-fill-mode",
|
||||
"animation-iteration-count", "animation-name", "animation-play-state",
|
||||
"animation-timing-function", "appearance", "azimuth", "backface-visibility",
|
||||
"background", "background-attachment", "background-blend-mode", "background-clip",
|
||||
"background-color", "background-image", "background-origin", "background-position",
|
||||
"background-repeat", "background-size", "baseline-shift", "binding",
|
||||
"bleed", "bookmark-label", "bookmark-level", "bookmark-state",
|
||||
"bookmark-target", "border", "border-bottom", "border-bottom-color",
|
||||
"border-bottom-left-radius", "border-bottom-right-radius",
|
||||
"border-bottom-style", "border-bottom-width", "border-collapse",
|
||||
"border-color", "border-image", "border-image-outset",
|
||||
"border-image-repeat", "border-image-slice", "border-image-source",
|
||||
"border-image-width", "border-left", "border-left-color",
|
||||
"border-left-style", "border-left-width", "border-radius", "border-right",
|
||||
"border-right-color", "border-right-style", "border-right-width",
|
||||
"border-spacing", "border-style", "border-top", "border-top-color",
|
||||
"border-top-left-radius", "border-top-right-radius", "border-top-style",
|
||||
"border-top-width", "border-width", "bottom", "box-decoration-break",
|
||||
"box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
|
||||
"caption-side", "clear", "clip", "color", "color-profile", "column-count",
|
||||
"column-fill", "column-gap", "column-rule", "column-rule-color",
|
||||
"column-rule-style", "column-rule-width", "column-span", "column-width",
|
||||
"columns", "content", "counter-increment", "counter-reset", "crop", "cue",
|
||||
"cue-after", "cue-before", "cursor", "direction", "display",
|
||||
"dominant-baseline", "drop-initial-after-adjust",
|
||||
"drop-initial-after-align", "drop-initial-before-adjust",
|
||||
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
|
||||
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
|
||||
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
|
||||
"float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
|
||||
"font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
|
||||
"font-stretch", "font-style", "font-synthesis", "font-variant",
|
||||
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
|
||||
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
|
||||
"font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
|
||||
"grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap",
|
||||
"grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap",
|
||||
"grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns",
|
||||
"grid-template-rows", "hanging-punctuation", "height", "hyphens",
|
||||
"icon", "image-orientation", "image-rendering", "image-resolution",
|
||||
"inline-box-align", "justify-content", "left", "letter-spacing",
|
||||
"line-break", "line-height", "line-stacking", "line-stacking-ruby",
|
||||
"line-stacking-shift", "line-stacking-strategy", "list-style",
|
||||
"list-style-image", "list-style-position", "list-style-type", "margin",
|
||||
"margin-bottom", "margin-left", "margin-right", "margin-top",
|
||||
"marker-offset", "marks", "marquee-direction", "marquee-loop",
|
||||
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
|
||||
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
|
||||
"nav-left", "nav-right", "nav-up", "object-fit", "object-position",
|
||||
"opacity", "order", "orphans", "outline",
|
||||
"outline-color", "outline-offset", "outline-style", "outline-width",
|
||||
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
|
||||
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
|
||||
"page", "page-break-after", "page-break-before", "page-break-inside",
|
||||
"page-policy", "pause", "pause-after", "pause-before", "perspective",
|
||||
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
|
||||
"presentation-level", "punctuation-trim", "quotes", "region-break-after",
|
||||
"region-break-before", "region-break-inside", "region-fragment",
|
||||
"rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
|
||||
"right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
|
||||
"ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
|
||||
"shape-outside", "size", "speak", "speak-as", "speak-header",
|
||||
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
|
||||
"tab-size", "table-layout", "target", "target-name", "target-new",
|
||||
"target-position", "text-align", "text-align-last", "text-decoration",
|
||||
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
|
||||
"text-decoration-style", "text-emphasis", "text-emphasis-color",
|
||||
"text-emphasis-position", "text-emphasis-style", "text-height",
|
||||
"text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
|
||||
"text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
|
||||
"text-wrap", "top", "transform", "transform-origin", "transform-style",
|
||||
"transition", "transition-delay", "transition-duration",
|
||||
"transition-property", "transition-timing-function", "unicode-bidi",
|
||||
"vertical-align", "visibility", "voice-balance", "voice-duration",
|
||||
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
|
||||
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
|
||||
"word-spacing", "word-wrap", "z-index",
|
||||
// SVG-specific
|
||||
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
|
||||
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
|
||||
"color-interpolation", "color-interpolation-filters",
|
||||
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
|
||||
"marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
|
||||
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
|
||||
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
|
||||
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
|
||||
"glyph-orientation-vertical", "text-anchor", "writing-mode"
|
||||
], propertyKeywords = keySet(propertyKeywords_);
|
||||
|
||||
var nonStandardPropertyKeywords_ = [
|
||||
"scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
|
||||
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
|
||||
"scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
|
||||
"searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
|
||||
"searchfield-results-decoration", "zoom"
|
||||
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
|
||||
|
||||
var fontProperties_ = [
|
||||
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
|
||||
"font-stretch", "font-weight", "font-style"
|
||||
], fontProperties = keySet(fontProperties_);
|
||||
|
||||
var counterDescriptors_ = [
|
||||
"additive-symbols", "fallback", "negative", "pad", "prefix", "range",
|
||||
"speak-as", "suffix", "symbols", "system"
|
||||
], counterDescriptors = keySet(counterDescriptors_);
|
||||
|
||||
var colorKeywords_ = [
|
||||
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
|
||||
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
|
||||
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
|
||||
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
|
||||
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
|
||||
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
|
||||
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
|
||||
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
|
||||
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
|
||||
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
|
||||
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
|
||||
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
|
||||
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
|
||||
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
|
||||
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
|
||||
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
|
||||
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
|
||||
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
|
||||
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
|
||||
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
|
||||
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
|
||||
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
|
||||
"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
|
||||
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
|
||||
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
|
||||
"whitesmoke", "yellow", "yellowgreen"
|
||||
], colorKeywords = keySet(colorKeywords_);
|
||||
|
||||
var valueKeywords_ = [
|
||||
"above", "absolute", "activeborder", "additive", "activecaption", "afar",
|
||||
"after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
|
||||
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
|
||||
"arabic-indic", "armenian", "asterisks", "attr", "auto", "avoid", "avoid-column", "avoid-page",
|
||||
"avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
|
||||
"bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
|
||||
"both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
|
||||
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
|
||||
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
|
||||
"cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
|
||||
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
|
||||
"col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
|
||||
"compact", "condensed", "contain", "content",
|
||||
"content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
|
||||
"cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
|
||||
"decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
|
||||
"destination-in", "destination-out", "destination-over", "devanagari", "difference",
|
||||
"disc", "discard", "disclosure-closed", "disclosure-open", "document",
|
||||
"dot-dash", "dot-dot-dash",
|
||||
"dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
|
||||
"element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
|
||||
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
|
||||
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
|
||||
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
|
||||
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
|
||||
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
|
||||
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
|
||||
"ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
|
||||
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
|
||||
"forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove",
|
||||
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
|
||||
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
|
||||
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
|
||||
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
|
||||
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
|
||||
"inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
|
||||
"italic", "japanese-formal", "japanese-informal", "justify", "kannada",
|
||||
"katakana", "katakana-iroha", "keep-all", "khmer",
|
||||
"korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
|
||||
"landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
|
||||
"line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
|
||||
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
|
||||
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
|
||||
"lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d",
|
||||
"media-controls-background", "media-current-time-display",
|
||||
"media-fullscreen-button", "media-mute-button", "media-play-button",
|
||||
"media-return-to-realtime-button", "media-rewind-button",
|
||||
"media-seek-back-button", "media-seek-forward-button", "media-slider",
|
||||
"media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
|
||||
"media-volume-slider-container", "media-volume-sliderthumb", "medium",
|
||||
"menu", "menulist", "menulist-button", "menulist-text",
|
||||
"menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
|
||||
"mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize",
|
||||
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
|
||||
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
|
||||
"ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
|
||||
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
|
||||
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
|
||||
"painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
|
||||
"pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
|
||||
"progress", "push-button", "radial-gradient", "radio", "read-only",
|
||||
"read-write", "read-write-plaintext-only", "rectangle", "region",
|
||||
"relative", "repeat", "repeating-linear-gradient",
|
||||
"repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
|
||||
"rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
|
||||
"rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
|
||||
"s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
|
||||
"scroll", "scrollbar", "se-resize", "searchfield",
|
||||
"searchfield-cancel-button", "searchfield-decoration",
|
||||
"searchfield-results-button", "searchfield-results-decoration",
|
||||
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
|
||||
"simp-chinese-formal", "simp-chinese-informal", "single",
|
||||
"skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
|
||||
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
|
||||
"small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
|
||||
"source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
|
||||
"square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
|
||||
"subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
|
||||
"table-caption", "table-cell", "table-column", "table-column-group",
|
||||
"table-footer-group", "table-header-group", "table-row", "table-row-group",
|
||||
"tamil",
|
||||
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
|
||||
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
|
||||
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
|
||||
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
|
||||
"trad-chinese-formal", "trad-chinese-informal",
|
||||
"translate", "translate3d", "translateX", "translateY", "translateZ",
|
||||
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
|
||||
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
|
||||
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
|
||||
"var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
|
||||
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
|
||||
"window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
|
||||
"xx-large", "xx-small"
|
||||
], valueKeywords = keySet(valueKeywords_);
|
||||
|
||||
var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
|
||||
.concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
|
||||
.concat(valueKeywords_);
|
||||
CodeMirror.registerHelper("hintWords", "css", allWords);
|
||||
|
||||
function tokenCComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while ((ch = stream.next()) != null) {
|
||||
if (maybeEnd && ch == "/") {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
}
|
||||
return ["comment", "comment"];
|
||||
}
|
||||
|
||||
CodeMirror.defineMIME("text/css", {
|
||||
documentTypes: documentTypes,
|
||||
mediaTypes: mediaTypes,
|
||||
mediaFeatures: mediaFeatures,
|
||||
mediaValueKeywords: mediaValueKeywords,
|
||||
propertyKeywords: propertyKeywords,
|
||||
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||
fontProperties: fontProperties,
|
||||
counterDescriptors: counterDescriptors,
|
||||
colorKeywords: colorKeywords,
|
||||
valueKeywords: valueKeywords,
|
||||
tokenHooks: {
|
||||
"/": function(stream, state) {
|
||||
if (!stream.eat("*")) return false;
|
||||
state.tokenize = tokenCComment;
|
||||
return tokenCComment(stream, state);
|
||||
}
|
||||
},
|
||||
name: "css"
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-scss", {
|
||||
mediaTypes: mediaTypes,
|
||||
mediaFeatures: mediaFeatures,
|
||||
mediaValueKeywords: mediaValueKeywords,
|
||||
propertyKeywords: propertyKeywords,
|
||||
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||
colorKeywords: colorKeywords,
|
||||
valueKeywords: valueKeywords,
|
||||
fontProperties: fontProperties,
|
||||
allowNested: true,
|
||||
tokenHooks: {
|
||||
"/": function(stream, state) {
|
||||
if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return ["comment", "comment"];
|
||||
} else if (stream.eat("*")) {
|
||||
state.tokenize = tokenCComment;
|
||||
return tokenCComment(stream, state);
|
||||
} else {
|
||||
return ["operator", "operator"];
|
||||
}
|
||||
},
|
||||
":": function(stream) {
|
||||
if (stream.match(/\s*\{/))
|
||||
return [null, "{"];
|
||||
return false;
|
||||
},
|
||||
"$": function(stream) {
|
||||
stream.match(/^[\w-]+/);
|
||||
if (stream.match(/^\s*:/, false))
|
||||
return ["variable-2", "variable-definition"];
|
||||
return ["variable-2", "variable"];
|
||||
},
|
||||
"#": function(stream) {
|
||||
if (!stream.eat("{")) return false;
|
||||
return [null, "interpolation"];
|
||||
}
|
||||
},
|
||||
name: "css",
|
||||
helperType: "scss"
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-less", {
|
||||
mediaTypes: mediaTypes,
|
||||
mediaFeatures: mediaFeatures,
|
||||
mediaValueKeywords: mediaValueKeywords,
|
||||
propertyKeywords: propertyKeywords,
|
||||
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||
colorKeywords: colorKeywords,
|
||||
valueKeywords: valueKeywords,
|
||||
fontProperties: fontProperties,
|
||||
allowNested: true,
|
||||
tokenHooks: {
|
||||
"/": function(stream, state) {
|
||||
if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return ["comment", "comment"];
|
||||
} else if (stream.eat("*")) {
|
||||
state.tokenize = tokenCComment;
|
||||
return tokenCComment(stream, state);
|
||||
} else {
|
||||
return ["operator", "operator"];
|
||||
}
|
||||
},
|
||||
"@": function(stream) {
|
||||
if (stream.eat("{")) return [null, "interpolation"];
|
||||
if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
if (stream.match(/^\s*:/, false))
|
||||
return ["variable-2", "variable-definition"];
|
||||
return ["variable-2", "variable"];
|
||||
},
|
||||
"&": function() {
|
||||
return ["atom", "atom"];
|
||||
}
|
||||
},
|
||||
name: "css",
|
||||
helperType: "less"
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-gss", {
|
||||
documentTypes: documentTypes,
|
||||
mediaTypes: mediaTypes,
|
||||
mediaFeatures: mediaFeatures,
|
||||
propertyKeywords: propertyKeywords,
|
||||
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||
fontProperties: fontProperties,
|
||||
counterDescriptors: counterDescriptors,
|
||||
colorKeywords: colorKeywords,
|
||||
valueKeywords: valueKeywords,
|
||||
supportsAtComponent: true,
|
||||
tokenHooks: {
|
||||
"/": function(stream, state) {
|
||||
if (!stream.eat("*")) return false;
|
||||
state.tokenize = tokenCComment;
|
||||
return tokenCComment(stream, state);
|
||||
}
|
||||
},
|
||||
name: "css",
|
||||
helperType: "gss"
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Closure Stylesheets (GSS) mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<link rel="stylesheet" href="../../addon/hint/show-hint.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="css.js"></script>
|
||||
<script src="../../addon/hint/show-hint.js"></script>
|
||||
<script src="../../addon/hint/css-hint.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Closure Stylesheets (GSS)</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Closure Stylesheets (GSS) mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
/* Some example Closure Stylesheets */
|
||||
|
||||
@provide 'some.styles';
|
||||
|
||||
@require 'other.styles';
|
||||
|
||||
@component {
|
||||
|
||||
@def FONT_FAMILY "Times New Roman", Georgia, Serif;
|
||||
@def FONT_SIZE_NORMAL 15px;
|
||||
@def FONT_NORMAL normal FONT_SIZE_NORMAL FONT_FAMILY;
|
||||
|
||||
@def BG_COLOR rgb(235, 239, 249);
|
||||
|
||||
@def DIALOG_BORDER_COLOR rgb(107, 144, 218);
|
||||
@def DIALOG_BG_COLOR BG_COLOR;
|
||||
|
||||
@def LEFT_HAND_NAV_WIDTH 180px;
|
||||
@def LEFT_HAND_NAV_PADDING 3px;
|
||||
|
||||
@defmixin size(WIDTH, HEIGHT) {
|
||||
width: WIDTH;
|
||||
height: HEIGHT;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: BG_COLOR;
|
||||
margin: 0;
|
||||
padding: 3em 6em;
|
||||
font: FONT_NORMAL;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#navigation a {
|
||||
font-weight: bold;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
background-color: DIALOG_BG_COLOR;
|
||||
border: 1px solid DIALOG_BORDER_COLOR;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: absolute;
|
||||
margin-left: add(LEFT_HAND_NAV_PADDING, /* padding left */
|
||||
LEFT_HAND_NAV_WIDTH,
|
||||
LEFT_HAND_NAV_PADDING); /* padding right */
|
||||
|
||||
}
|
||||
|
||||
.logo {
|
||||
@mixin size(150px, 55px);
|
||||
background-image: url('http://www.google.com/images/logo_sm.gif');
|
||||
}
|
||||
|
||||
}
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
extraKeys: {"Ctrl-Space": "autocomplete"},
|
||||
lineNumbers: true,
|
||||
matchBrackets: "text/x-less",
|
||||
mode: "text/x-gss"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>A mode for <a href="https://github.com/google/closure-stylesheets">Closure Stylesheets</a> (GSS).</p>
|
||||
<p><strong>MIME type defined:</strong> <code>text/x-gss</code>.</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#gss_*">normal</a>, <a href="../../test/index.html#verbose,gss_*">verbose</a>.</p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,17 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-gss");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "gss"); }
|
||||
|
||||
MT("atComponent",
|
||||
"[def @component] {",
|
||||
"[tag foo] {",
|
||||
" [property color]: [keyword black];",
|
||||
"}",
|
||||
"}");
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,75 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: CSS mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<link rel="stylesheet" href="../../addon/hint/show-hint.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="css.js"></script>
|
||||
<script src="../../addon/hint/show-hint.js"></script>
|
||||
<script src="../../addon/hint/css-hint.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">CSS</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>CSS mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
/* Some example CSS */
|
||||
|
||||
@import url("something.css");
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 3em 6em;
|
||||
font-family: tahoma, arial, sans-serif;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#navigation a {
|
||||
font-weight: bold;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
h1:before, h2:before {
|
||||
content: "::";
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: courier, monospace;
|
||||
font-size: 80%;
|
||||
color: #418A8A;
|
||||
}
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
extraKeys: {"Ctrl-Space": "autocomplete"},
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/css</code>, <code>text/x-scss</code> (<a href="scss.html">demo</a>), <code>text/x-less</code> (<a href="less.html">demo</a>).</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#css_*">normal</a>, <a href="../../test/index.html#verbose,css_*">verbose</a>.</p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,152 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: LESS mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="css.js"></script>
|
||||
<style>.CodeMirror {border: 1px solid #ddd; line-height: 1.2;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">LESS</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>LESS mode</h2>
|
||||
<form><textarea id="code" name="code">@media screen and (device-aspect-ratio: 16/9) { … }
|
||||
@media screen and (device-aspect-ratio: 1280/720) { … }
|
||||
@media screen and (device-aspect-ratio: 2560/1440) { … }
|
||||
|
||||
html:lang(fr-be)
|
||||
|
||||
tr:nth-child(2n+1) /* represents every odd row of an HTML table */
|
||||
|
||||
img:nth-of-type(2n+1) { float: right; }
|
||||
img:nth-of-type(2n) { float: left; }
|
||||
|
||||
body > h2:not(:first-of-type):not(:last-of-type)
|
||||
|
||||
html|*:not(:link):not(:visited)
|
||||
*|*:not(:hover)
|
||||
p::first-line { text-transform: uppercase }
|
||||
|
||||
@namespace foo url(http://www.example.com);
|
||||
foo|h1 { color: blue } /* first rule */
|
||||
|
||||
span[hello="Ocean"][goodbye="Land"]
|
||||
|
||||
E[foo]{
|
||||
padding:65px;
|
||||
}
|
||||
|
||||
input[type="search"]::-webkit-search-decoration,
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
|
||||
}
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
.btn {
|
||||
// reset here as of 2.0.3 due to Recess property order
|
||||
border-color: #ccc;
|
||||
border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
|
||||
}
|
||||
fieldset span button, fieldset span input[type="file"] {
|
||||
font-size:12px;
|
||||
font-family:Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.rounded-corners (@radius: 5px) {
|
||||
border-radius: @radius;
|
||||
-webkit-border-radius: @radius;
|
||||
-moz-border-radius: @radius;
|
||||
}
|
||||
|
||||
@import url("something.css");
|
||||
|
||||
@light-blue: hsl(190, 50%, 65%);
|
||||
|
||||
#menu {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 3;
|
||||
clear: both;
|
||||
display: block;
|
||||
background-color: @blue;
|
||||
height: 42px;
|
||||
border-top: 2px solid lighten(@alpha-blue, 20%);
|
||||
border-bottom: 2px solid darken(@alpha-blue, 25%);
|
||||
.box-shadow(0, 1px, 8px, 0.6);
|
||||
-moz-box-shadow: 0 0 0 #000; // Because firefox sucks.
|
||||
|
||||
&.docked {
|
||||
background-color: hsla(210, 60%, 40%, 0.4);
|
||||
}
|
||||
&:hover {
|
||||
background-color: @blue;
|
||||
}
|
||||
|
||||
#dropdown {
|
||||
margin: 0 0 0 117px;
|
||||
padding: 0;
|
||||
padding-top: 5px;
|
||||
display: none;
|
||||
width: 190px;
|
||||
border-top: 2px solid @medium;
|
||||
color: @highlight;
|
||||
border: 2px solid darken(@medium, 25%);
|
||||
border-left-color: darken(@medium, 15%);
|
||||
border-right-color: darken(@medium, 15%);
|
||||
border-top-width: 0;
|
||||
background-color: darken(@medium, 10%);
|
||||
ul {
|
||||
padding: 0px;
|
||||
}
|
||||
li {
|
||||
font-size: 14px;
|
||||
display: block;
|
||||
text-align: left;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
a {
|
||||
display: block;
|
||||
padding: 0px 15px;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
&:hover {
|
||||
background-color: darken(@medium, 15%);
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.border-radius(5px, bottom);
|
||||
.box-shadow(0, 6px, 8px, 0.5);
|
||||
}
|
||||
}
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers : true,
|
||||
matchBrackets : true,
|
||||
mode: "text/x-less"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>The LESS mode is a sub-mode of the <a href="index.html">CSS mode</a> (defined in <code>css.js</code>).</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#less_*">normal</a>, <a href="../../test/index.html#verbose,less_*">verbose</a>.</p>
|
||||
</article>
|
||||
@@ -0,0 +1,54 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); }
|
||||
|
||||
MT("variable",
|
||||
"[variable-2 @base]: [atom #f04615];",
|
||||
"[qualifier .class] {",
|
||||
" [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]",
|
||||
" [property color]: [variable saturate]([variable-2 @base], [number 5%]);",
|
||||
"}");
|
||||
|
||||
MT("amp",
|
||||
"[qualifier .child], [qualifier .sibling] {",
|
||||
" [qualifier .parent] [atom &] {",
|
||||
" [property color]: [keyword black];",
|
||||
" }",
|
||||
" [atom &] + [atom &] {",
|
||||
" [property color]: [keyword red];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("mixin",
|
||||
"[qualifier .mixin] ([variable dark]; [variable-2 @color]) {",
|
||||
" [property color]: [atom darken]([variable-2 @color], [number 10%]);",
|
||||
"}",
|
||||
"[qualifier .mixin] ([variable light]; [variable-2 @color]) {",
|
||||
" [property color]: [atom lighten]([variable-2 @color], [number 10%]);",
|
||||
"}",
|
||||
"[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {",
|
||||
" [property display]: [atom block];",
|
||||
"}",
|
||||
"[variable-2 @switch]: [variable light];",
|
||||
"[qualifier .class] {",
|
||||
" [qualifier .mixin]([variable-2 @switch]; [atom #888]);",
|
||||
"}");
|
||||
|
||||
MT("nest",
|
||||
"[qualifier .one] {",
|
||||
" [def @media] ([property width]: [number 400px]) {",
|
||||
" [property font-size]: [number 1.2em];",
|
||||
" [def @media] [attribute print] [keyword and] [property color] {",
|
||||
" [property color]: [keyword blue];",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
|
||||
MT("interpolation", ".@{[variable foo]} { [property font-weight]: [atom bold]; }");
|
||||
})();
|
||||
@@ -0,0 +1,157 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: SCSS mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="css.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">SCSS</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>SCSS mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
/* Some example SCSS */
|
||||
|
||||
@import "compass/css3";
|
||||
$variable: #333;
|
||||
|
||||
$blue: #3bbfce;
|
||||
$margin: 16px;
|
||||
|
||||
.content-navigation {
|
||||
#nested {
|
||||
background-color: black;
|
||||
}
|
||||
border-color: $blue;
|
||||
color:
|
||||
darken($blue, 9%);
|
||||
}
|
||||
|
||||
.border {
|
||||
padding: $margin / 2;
|
||||
margin: $margin / 2;
|
||||
border-color: $blue;
|
||||
}
|
||||
|
||||
@mixin table-base {
|
||||
th {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
td, th {padding: 2px}
|
||||
}
|
||||
|
||||
table.hl {
|
||||
margin: 2em 0;
|
||||
td.ln {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
font: {
|
||||
family: serif;
|
||||
weight: bold;
|
||||
size: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin left($dist) {
|
||||
float: left;
|
||||
margin-left: $dist;
|
||||
}
|
||||
|
||||
#data {
|
||||
@include left(10px);
|
||||
@include table-base;
|
||||
}
|
||||
|
||||
.source {
|
||||
@include flow-into(target);
|
||||
border: 10px solid green;
|
||||
margin: 20px;
|
||||
width: 200px; }
|
||||
|
||||
.new-container {
|
||||
@include flow-from(target);
|
||||
border: 10px solid red;
|
||||
margin: 20px;
|
||||
width: 200px; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 3em 6em;
|
||||
font-family: tahoma, arial, sans-serif;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
@mixin yellow() {
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.big {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nested {
|
||||
@include border-radius(3px);
|
||||
@extend .big;
|
||||
p {
|
||||
background: whitesmoke;
|
||||
a {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#navigation a {
|
||||
font-weight: bold;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
h1:before, h2:before {
|
||||
content: "::";
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: courier, monospace;
|
||||
font-size: 80%;
|
||||
color: #418A8A;
|
||||
}
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-scss"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>The SCSS mode is a sub-mode of the <a href="index.html">CSS mode</a> (defined in <code>css.js</code>).</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#scss_*">normal</a>, <a href="../../test/index.html#verbose,scss_*">verbose</a>.</p>
|
||||
|
||||
</article>
|
||||
@@ -0,0 +1,110 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }
|
||||
|
||||
MT('url_with_quotation',
|
||||
"[tag foo] { [property background]:[atom url]([string test.jpg]) }");
|
||||
|
||||
MT('url_with_double_quotes',
|
||||
"[tag foo] { [property background]:[atom url]([string \"test.jpg\"]) }");
|
||||
|
||||
MT('url_with_single_quotes',
|
||||
"[tag foo] { [property background]:[atom url]([string \'test.jpg\']) }");
|
||||
|
||||
MT('string',
|
||||
"[def @import] [string \"compass/css3\"]");
|
||||
|
||||
MT('important_keyword',
|
||||
"[tag foo] { [property background]:[atom url]([string \'test.jpg\']) [keyword !important] }");
|
||||
|
||||
MT('variable',
|
||||
"[variable-2 $blue]:[atom #333]");
|
||||
|
||||
MT('variable_as_attribute',
|
||||
"[tag foo] { [property color]:[variable-2 $blue] }");
|
||||
|
||||
MT('numbers',
|
||||
"[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }");
|
||||
|
||||
MT('number_percentage',
|
||||
"[tag foo] { [property width]:[number 80%] }");
|
||||
|
||||
MT('selector',
|
||||
"[builtin #hello][qualifier .world]{}");
|
||||
|
||||
MT('singleline_comment',
|
||||
"[comment // this is a comment]");
|
||||
|
||||
MT('multiline_comment',
|
||||
"[comment /*foobar*/]");
|
||||
|
||||
MT('attribute_with_hyphen',
|
||||
"[tag foo] { [property font-size]:[number 10px] }");
|
||||
|
||||
MT('string_after_attribute',
|
||||
"[tag foo] { [property content]:[string \"::\"] }");
|
||||
|
||||
MT('directives',
|
||||
"[def @include] [qualifier .mixin]");
|
||||
|
||||
MT('basic_structure',
|
||||
"[tag p] { [property background]:[keyword red]; }");
|
||||
|
||||
MT('nested_structure',
|
||||
"[tag p] { [tag a] { [property color]:[keyword red]; } }");
|
||||
|
||||
MT('mixin',
|
||||
"[def @mixin] [tag table-base] {}");
|
||||
|
||||
MT('number_without_semicolon',
|
||||
"[tag p] {[property width]:[number 12]}",
|
||||
"[tag a] {[property color]:[keyword red];}");
|
||||
|
||||
MT('atom_in_nested_block',
|
||||
"[tag p] { [tag a] { [property color]:[atom #000]; } }");
|
||||
|
||||
MT('interpolation_in_property',
|
||||
"[tag foo] { #{[variable-2 $hello]}:[number 2]; }");
|
||||
|
||||
MT('interpolation_in_selector',
|
||||
"[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }");
|
||||
|
||||
MT('interpolation_error',
|
||||
"[tag foo]#{[variable foo]} { [property color]:[atom #000]; }");
|
||||
|
||||
MT("divide_operator",
|
||||
"[tag foo] { [property width]:[number 4] [operator /] [number 2] }");
|
||||
|
||||
MT('nested_structure_with_id_selector',
|
||||
"[tag p] { [builtin #hello] { [property color]:[keyword red]; } }");
|
||||
|
||||
MT('indent_mixin',
|
||||
"[def @mixin] [tag container] (",
|
||||
" [variable-2 $a]: [number 10],",
|
||||
" [variable-2 $b]: [number 10])",
|
||||
"{}");
|
||||
|
||||
MT('indent_nested',
|
||||
"[tag foo] {",
|
||||
" [tag bar] {",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT('indent_parentheses',
|
||||
"[tag foo] {",
|
||||
" [property color]: [atom darken]([variable-2 $blue],",
|
||||
" [number 9%]);",
|
||||
"}");
|
||||
|
||||
MT('indent_vardef',
|
||||
"[variable-2 $name]:",
|
||||
" [string 'val'];",
|
||||
"[tag tag] {",
|
||||
" [tag inner] {",
|
||||
" [property margin]: [number 3px];",
|
||||
" }",
|
||||
"}");
|
||||
})();
|
||||