Fossil

Check-in [240646ef7d]
Login

Check-in [240646ef7d]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Simplified pikchrshow markup alignment selection to a single checkbox. Related CSS/layout tweaks.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 240646ef7d8eb2ae5684b54c8f444bd9c8cfd3cc65b96e8a0ea7f463452df855
User & Date: stephan 2020-09-12 02:58:27.451
Context
2020-09-12
03:22
Replaced predefined pikchr script list with the new pikchr examples/*.txt (was tests/*.txt) and cache non-error preview responses for those scripts. This halves the over-the-wire size of fossil.page.pikchrshow.js. ... (check-in: 62a5d0cfb9 user: stephan tags: trunk)
02:58
Simplified pikchrshow markup alignment selection to a single checkbox. Related CSS/layout tweaks. ... (check-in: 240646ef7d user: stephan tags: trunk)
02:24
Update pikchr.c to the latest. This also required a small correction to text alignment in figure 6 of branching.wiki ... (check-in: c3bb7cd22a user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/default.css.
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
   we can include multiple INPUT elements (e.g. a set of radio
   buttons). Note that these elements must sometimes be BLOCK elements
   (e.g. DIV) so that certain nesting constructs are legal.
*/
.input-with-label {
  border: 1px inset rgba(128, 128, 128, 0.5);
  border-radius: 0.25em;
  padding: 0.15em 0.25em;
  margin: 0 0.5em;
  display: inline-block;
  cursor: default;
  white-space: nowrap;
}
.input-with-label > * {
  vertical-align: middle;







|







1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
   we can include multiple INPUT elements (e.g. a set of radio
   buttons). Note that these elements must sometimes be BLOCK elements
   (e.g. DIV) so that certain nesting constructs are legal.
*/
.input-with-label {
  border: 1px inset rgba(128, 128, 128, 0.5);
  border-radius: 0.25em;
  padding: 0.1em;
  margin: 0 0.5em;
  display: inline-block;
  cursor: default;
  white-space: nowrap;
}
.input-with-label > * {
  vertical-align: middle;
1138
1139
1140
1141
1142
1143
1144




1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
}
.input-with-label > input[type=text] {
  margin: 0;
}
.input-with-label > textarea {
  margin: 0;
}




.input-with-label > input[type=checkbox] {
  vertical-align: sub;
}
.input-with-label > input[type=radio] {
  vertical-align: sub;
}
.input-with-label > label {
  font-weight: initial;
  margin: 0 0.25em 0 0.25em;
  vertical-align: middle;
}








>
>
>
>

|


|







1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
}
.input-with-label > input[type=text] {
  margin: 0;
}
.input-with-label > textarea {
  margin: 0;
}
/* Browsers are unfortunately inconsistent in how they
   align checkboxes and radio buttons, even if they're
   given the same vertical-align value. 'middle' seems to
   be the least bad option, rather than the ideal. */
.input-with-label > input[type=checkbox] {
  vertical-align: middle;
}
.input-with-label > input[type=radio] {
  vertical-align: middle;
}
.input-with-label > label {
  font-weight: initial;
  margin: 0 0.25em 0 0.25em;
  vertical-align: middle;
}

Changes to src/fossil.page.pikchrshow.js.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52



53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
      btnSubmit: E('#pikchr-submit-preview'),
      cbDarkMode: E('#flipcolors-wrapper > input[type=checkbox]'),
      taContent: E('#content'),
      taPreviewText: D.attr(D.textarea(), 'rows', 20, 'cols', 60,
                            'readonly', true),
      uiControls: E('#pikchrshow-controls'),
      previewModeToggle: D.button("Preview mode"),
      selectAlignment: D.append(
        D.select(/*alignment for markup blocks*/),
        D.option('', 'Markup Alignment'),
        D.option('', 'left (default)'),
        D.option('center', 'center')
      )
    };

    ////////////////////////////////////////////////////////////
    // Setup markup alignment selection...
    D.disable(P.e.selectAlignment.options[0]
      /*has to be done after creation for default selection to work*/
    );
    P.e.selectAlignment.addEventListener('change', function(ev){
      /* Update markdown/fossil wiki preview if it's active */
      if(P.previewMode==1 || P.previewMode==2){
        P.renderPreview();
      }
    }, false);




    ////////////////////////////////////////////////////////////
    // Setup the preview fieldset's LEGEND element...
    D.append( P.e.previewLegend,
              P.e.previewModeToggle,

              P.e.previewModeLabel,
              P.e.previewCopyButton,
              D.addClass(P.e.selectAlignment, 'hidden') );

    ////////////////////////////////////////////////////////////
    // Setup clipboard-copy of markup/SVG...
    F.copyButton(P.e.previewCopyButton, {copyFromElement: P.e.taPreviewText});
    P.e.previewCopyButton.addEventListener('text-copied', D.flashOnce.eventHandler, false);

    ////////////////////////////////////////////////////////////







|
|
<
<
<
<




<
<
<
|





>
>
>





>
|
|
|







27
28
29
30
31
32
33
34
35




36
37
38
39



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
      btnSubmit: E('#pikchr-submit-preview'),
      cbDarkMode: E('#flipcolors-wrapper > input[type=checkbox]'),
      taContent: E('#content'),
      taPreviewText: D.attr(D.textarea(), 'rows', 20, 'cols', 60,
                            'readonly', true),
      uiControls: E('#pikchrshow-controls'),
      previewModeToggle: D.button("Preview mode"),
      markupAlignCenter: D.attr(D.checkbox(), 'id','markup-align-center'),
      markupAlignWrapper: D.span()//D.addClass(D.span(), 'input-with-label')




    };

    ////////////////////////////////////////////////////////////
    // Setup markup alignment selection...



    P.e.markupAlignCenter.addEventListener('change', function(ev){
      /* Update markdown/fossil wiki preview if it's active */
      if(P.previewMode==1 || P.previewMode==2){
        P.renderPreview();
      }
    }, false);
    D.append(P.e.markupAlignWrapper,
             P.e.markupAlignCenter,
             D.label(P.e.markupAlignCenter, "Align center?"));

    ////////////////////////////////////////////////////////////
    // Setup the preview fieldset's LEGEND element...
    D.append( P.e.previewLegend,
              P.e.previewModeToggle,
              '\u00a0',
              P.e.previewCopyButton,
              P.e.previewModeLabel,
              P.e.markupAlignWrapper );

    ////////////////////////////////////////////////////////////
    // Setup clipboard-copy of markup/SVG...
    F.copyButton(P.e.previewCopyButton, {copyFromElement: P.e.taPreviewText});
    P.e.previewCopyButton.addEventListener('text-copied', D.flashOnce.eventHandler, false);

    ////////////////////////////////////////////////////////////
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
                   'slow connection/server.',
                   D.br(),D.br(),
                   'Pikchr scripts may also be dragged/dropped from ',
                   'the local filesystem into the text area, but ',
                   'the auto-preview option does not apply to them.'
                  )
        )
      ).childNodes.forEach(function(ch){
        ch.style.margin = "0 0.25em";
      });
      D.append(P.e.uiControls, cbWrap);
      P.predefinedPiks.forEach(function(script,ndx){
        const opt = D.option(script.code ? script.code.trim() :'', script.name);
        D.append(selectScript, opt);
        if(!ndx) selectScript.selectedIndex = 0 /*timing/ordering workaround*/;
        if(!script.code) D.disable(opt);
      });







|

|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
                   'slow connection/server.',
                   D.br(),D.br(),
                   'Pikchr scripts may also be dragged/dropped from ',
                   'the local filesystem into the text area, but ',
                   'the auto-preview option does not apply to them.'
                  )
        )
      )/*.childNodes.forEach(function(ch){
        ch.style.margin = "0 0.25em";
      })*/;
      D.append(P.e.uiControls, cbWrap);
      P.predefinedPiks.forEach(function(script,ndx){
        const opt = D.option(script.code ? script.code.trim() :'', script.name);
        D.append(selectScript, opt);
        if(!ndx) selectScript.selectedIndex = 0 /*timing/ordering workaround*/;
        if(!script.code) D.disable(opt);
      });
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
      P.response.inputText = P.e.taContent.value;
      P.response.raw = P.e.previewTarget.innerHTML;
      P.renderPreview()/*it's already rendered, but this gets all
                         labels/headers in sync.*/;
    }    
  }/*F.onPageLoad()*/);

  /* Shows or hides P.e.selectAlignment */
  const showMarkupAlignment = function(showIt){
    P.e.selectAlignment.classList[showIt ? 'remove' : 'add']('hidden');
  };

  /**
     Updates the preview view based on the current preview mode and
     error state.
  */
  P.renderPreview = function f(){
    if(!f.hasOwnProperty('rxNonce')){
      f.rxNonce = /<!--.+-->\r?\n?/g /*pikchr nonce comments*/;
    }
    const preTgt = this.e.previewTarget;
    if(this.response.isError){
      preTgt.innerHTML = this.response.raw;
      D.addClass(preTgt, 'error');
      this.e.previewModeLabel.innerText = "Error";
      return;
    }
    D.removeClass(preTgt, 'error');
    D.removeClass(P.e.previewCopyButton, 'disabled');
    D.enable(this.e.previewModeToggle);
    let label;
    switch(this.previewMode){
    case 0:
      label = "Rendered SVG";
      showMarkupAlignment(false);
      preTgt.innerHTML = this.response.raw;
      this.e.taPreviewText.value = this.response.raw.replace(f.rxNonce, '')/*for copy button*/;
      break;
    case 1:
      label = "Markdown";
      showMarkupAlignment(true);
      this.e.taPreviewText.value = [
        '```pikchr'+(this.e.selectAlignment.value
                     ? ' '+this.e.selectAlignment.value : ''),
        this.response.inputText, '```'
      ].join('\n');
      D.append(D.clearElement(preTgt), this.e.taPreviewText);
      break;
    case 2:
      label = "Fossil wiki";
      showMarkupAlignment(true);
      this.e.taPreviewText.value = [
        '<verbatim type="pikchr',
        this.e.selectAlignment.value ? ' '+this.e.selectAlignment.value : '',
        '">', this.response.inputText, '</verbatim>'
      ].join('');
      D.append(D.clearElement(preTgt), this.e.taPreviewText);
      break;
    case 3:
      label = "Raw SVG";
      showMarkupAlignment(false);







|

|



















|



|








|
<









|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
      P.response.inputText = P.e.taContent.value;
      P.response.raw = P.e.previewTarget.innerHTML;
      P.renderPreview()/*it's already rendered, but this gets all
                         labels/headers in sync.*/;
    }    
  }/*F.onPageLoad()*/);

  /* Shows or hides P.e.markupAlignWrapper */
  const showMarkupAlignment = function(showIt){
    P.e.markupAlignWrapper.classList[showIt ? 'remove' : 'add']('hidden');
  };

  /**
     Updates the preview view based on the current preview mode and
     error state.
  */
  P.renderPreview = function f(){
    if(!f.hasOwnProperty('rxNonce')){
      f.rxNonce = /<!--.+-->\r?\n?/g /*pikchr nonce comments*/;
    }
    const preTgt = this.e.previewTarget;
    if(this.response.isError){
      preTgt.innerHTML = this.response.raw;
      D.addClass(preTgt, 'error');
      this.e.previewModeLabel.innerText = "Error";
      return;
    }
    D.removeClass(preTgt, 'error');
    D.removeClass(P.e.previewCopyButton, 'disabled');
    D.enable(this.e.previewModeToggle, this.e.markupAlignCenter);
    let label;
    switch(this.previewMode){
    case 0:
      label = "SVG";
      showMarkupAlignment(false);
      preTgt.innerHTML = this.response.raw;
      this.e.taPreviewText.value = this.response.raw.replace(f.rxNonce, '')/*for copy button*/;
      break;
    case 1:
      label = "Markdown";
      showMarkupAlignment(true);
      this.e.taPreviewText.value = [
        '```pikchr'+(this.e.markupAlignCenter.checked? ' center' : ''),

        this.response.inputText, '```'
      ].join('\n');
      D.append(D.clearElement(preTgt), this.e.taPreviewText);
      break;
    case 2:
      label = "Fossil wiki";
      showMarkupAlignment(true);
      this.e.taPreviewText.value = [
        '<verbatim type="pikchr',
        this.e.markupAlignCenter.checked ? ' center' : '',
        '">', this.response.inputText, '</verbatim>'
      ].join('');
      D.append(D.clearElement(preTgt), this.e.taPreviewText);
      break;
    case 3:
      label = "Raw SVG";
      showMarkupAlignment(false);
247
248
249
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
     the rendered SVG content or error report.
  */
  P.preview = function fp(){
    if(!fp.hasOwnProperty('toDisable')){
      fp.toDisable = [
        /* input elements to disable during ajax operations */
        this.e.btnSubmit, this.e.taContent,
        this.e.selectAlignment,
        this.e.cbAutoPreview, this.e.selectScript
        /* handled separately: previewModeToggle, previewCopyButton */

      ];
      fp.target = this.e.previewTarget;
      fp.updateView = function(c,isError){
        P.previewMode = 0;
        P.response.raw = c;
        P.response.isError = isError;
        D.enable(fp.toDisable);
        P.renderPreview();
      };
    }
    D.disable(fp.toDisable, this.e.previewModeToggle);
    D.addClass(this.e.previewCopyButton, 'disabled');
    const content = this.e.taContent.value.trim();
    this.response.raw = undefined;
    this.response.inputText = content;
    if(!content){
      fp.updateView("No pikchr content!",true);
      return this;







<

|
>










|







243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
     the rendered SVG content or error report.
  */
  P.preview = function fp(){
    if(!fp.hasOwnProperty('toDisable')){
      fp.toDisable = [
        /* input elements to disable during ajax operations */
        this.e.btnSubmit, this.e.taContent,

        this.e.cbAutoPreview, this.e.selectScript
        /* handled separately: previewModeToggle, previewCopyButton,
           markupAlignCenter */
      ];
      fp.target = this.e.previewTarget;
      fp.updateView = function(c,isError){
        P.previewMode = 0;
        P.response.raw = c;
        P.response.isError = isError;
        D.enable(fp.toDisable);
        P.renderPreview();
      };
    }
    D.disable(fp.toDisable, this.e.previewModeToggle, this.e.markupAlignCenter);
    D.addClass(this.e.previewCopyButton, 'disabled');
    const content = this.e.taContent.value.trim();
    this.response.raw = undefined;
    this.response.inputText = content;
    if(!content){
      fp.updateView("No pikchr content!",true);
      return this;
Changes to src/pikchrshow.c.
95
96
97
98
99
100
101
102
103



104
105
106
107
108
109
110
111




112
113
114
115
116
117
118
119
120
  CX("#pikchrshow-controls {" /* where the buttons live */
     "display: flex; flex-direction: row; "
     "align-items: center; flex-wrap: wrap;"
     "}");
  CX("#pikchrshow-controls > * {"
     "display: inline; margin: 0 0.25em 0.5em 0;"
     "}");
  CX("#pikchrshow-controls > .input-with-label > * {"
     "cursor: pointer;"



     "}");
  CX("#pikchrshow-output.dark-mode svg {"
     /* Flip the colors to approximate a dark theme look */
     "filter: invert(1) hue-rotate(180deg);"
     "}");
  CX("#sbs-wrapper > fieldset {"
     "padding: 0.25em 0.5em; border-radius: 0.25em;"
     "}");




  CX("fieldset > legend > *,"
     "fieldset > legend > .copy-button"
     /* ^^^ better-match .copy-button selector required to override
        default */
     "{margin-right: 0.5em}");
  CX(".dragover {border: 0.5em dotted rgba(0,255,0,0.6)}");
  CX("</style>");
  CX("<div>Input pikchr code and tap Preview to render it:</div>");
  CX("<div id='sbs-wrapper'>");







|

>
>
>





|


>
>
>
>
|
|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  CX("#pikchrshow-controls {" /* where the buttons live */
     "display: flex; flex-direction: row; "
     "align-items: center; flex-wrap: wrap;"
     "}");
  CX("#pikchrshow-controls > * {"
     "display: inline; margin: 0 0.25em 0.5em 0;"
     "}");
  CX("#pikchrshow-output-wrapper label {"
     "cursor: pointer;"
     "}");
  CX("body.pikchrshow .input-with-label > * {"
     "margin: 0 0.2em; cursor: pointer;"
     "}");
  CX("#pikchrshow-output.dark-mode svg {"
     /* Flip the colors to approximate a dark theme look */
     "filter: invert(1) hue-rotate(180deg);"
     "}");
  CX("#pikchrshow-output-wrapper {"
     "padding: 0.25em 0.5em; border-radius: 0.25em;"
     "}");
  CX("#pikchrshow-output-wrapper > legend {"
     "display: flex; flex-direction: row;"
     "align-items: center;"
     "}");
  CX("#pikchrshow-output-wrapper > legend > *,"
     "#pikchrshow-output-wrapper > legend > .copy-button"
     /* ^^^ better-match .copy-button selector required to override
        default */
     "{margin-right: 0.5em}");
  CX(".dragover {border: 0.5em dotted rgba(0,255,0,0.6)}");
  CX("</style>");
  CX("<div>Input pikchr code and tap Preview to render it:</div>");
  CX("<div id='sbs-wrapper'>");