gustafn
committed
on 20 Jun 17
Fix broken links
openacs-4/.../tcl/richtext-procs.tcl (+118 -9)
1 1 ad_library {
2 2
3 3     CKEditor 4 integration with the richtext widget of acs-templating.
4 4
5 5     This script defines the following two procs:
6 6
7 7        ::richtext-ckeditor4::initialize_widget
8 8        ::richtext-ckeditor4::render_widgets   
9 9    
10 10     @author Gustaf Neumann
11 11     @creation-date 1 Jan 2016
12 12     @cvs-id $Id$
13 13 }
14 14
15 15 namespace eval ::richtext::ckeditor4 {
16 16
  17     set version 4.5.11
  18     set ck_package standard
  19    
17 20     ad_proc initialize_widget {
18 21         -form_id
19 22         -text_id
20 23         {-options {}}
21 24     } {
22 25        
23 26         Initialize an CKEditor richtext editor widget.
24 27        
25 28     } {
26 29         ns_log debug "initialize CKEditor instance with <$options>"
27 30
28 31         # allow per default all classes, unless the user has specified
29 32         # it differently
30 33         if {![dict exists $options extraAllowedContent]} {
31 34             dict set options extraAllowedContent {*(*)}
32 35         }
33 36        
34 37         # The richtext widget might be specified by "options {editor
35 38         # ckeditor4}" or via the package parameter "RichTextEditor" of
36 39         # acs-templating.
 
62 65         }
63 66         if {[dict exists $options skin]} {
64 67             lappend ckOptionsList "skin: '[dict get $options skin]'"
65 68         }
66 69         if {[dict exists $options customConfig]} {
67 70             lappend ckOptionsList "customConfig: '[dict get $options customConfig]'"
68 71         }
69 72         if {[dict exists $options extraAllowedContent]} {
70 73             lappend ckOptionsList "extraAllowedContent: '[dict get $options extraAllowedContent]'"
71 74         }
72 75
73 76         set ckOptions [join $ckOptionsList ", "]
74 77        
75 78         #
76 79         # Add the configuration via body script
77 80         #
78 81         template::add_script -section body -script [subst {
79 82             CKEDITOR.replace( '$text_id', {$ckOptions} );
80 83         }]
81 84
82           template::head::add_javascript -src "//cdn.ckeditor.com/4.5.11/standard/ckeditor.js"
83  
84 85         #
85           # add required directives for content security policies
  86         # Load the editor and everything necessary to the current page.
86 87         #
87           security::csp::require script-src 'unsafe-eval'
88           security::csp::require -force script-src 'unsafe-inline'
89           security::csp::require script-src cdn.ckeditor.com
90           security::csp::require style-src cdn.ckeditor.com
91           security::csp::require img-src cdn.ckeditor.com
  88         ::richtext::ckeditor4::add_editor
92 89        
93 90         #
94 91         # do we need render_widgets?
95 92         #
96 93         return ""
97 94     }
98 95
99 96
100 97     ad_proc render_widgets {} {
101 98
102 99         Render the ckeditor4 rich-text widgets. This function is created
103 100         at a time when all rich-text widgets of this page are already
104 101         initialized. The function is controlled via the global variables
105 102
106 103            ::acs_blank_master(ckeditor4)
107 104            ::acs_blank_master__htmlareas
108 105        
109 106     } {
110 107         #
111 108         # In case no ckeditor4 instances are created, nothing has to be
112 109         # done.
113 110         #
114 111         if {![info exists ::acs_blank_master(ckeditor4)]} {
115 112             return
116 113         }
117 114         #
118 115         # Since "template::head::add_javascript -src ..." prevents
119 116         # loading the same resource multiple times, we can perform the
120 117         # load in the per-widget initialization and we are done here.
121 118         #
122 119     }
123 120
  121    
  122     ad_proc ::richtext::ckeditor4::add_editor {
  123         {-ck_package ""}
  124         {-version ""}
  125     } {
  126
  127         Add the necessary JavaScript and other files to the current
  128         page. The naming is modeled after "add_script", "add_css",
  129         ... but is intended to care about everything necessary,
  130         including the content security policies. Similar naming
  131         conventions should be used for other editors as well.
  132
  133         This function can be as well used from other packages, such
  134         e.g. from the xowiki form-fields, which provide a much higher
  135         customization.
  136        
  137     } {
  138         #
  139         # If no version or ck editor package are specified, use the
  140         # namespaced variables as default.
  141         #
  142         if {$version eq ""} {
  143             set version ${::richtext::ckeditor4::version}
124 144         }
  145         if {$ck_package eq ""} {
  146             set ck_package ${::richtext::ckeditor4::ck_package}
  147         }
125 148
  149         set suffix $version/$ck_package/ckeditor.js
  150         set resources $::acs::rootdir/packages/richtext-ckeditor4/www/resources
  151        
  152         if {[file exists $resources/$suffix]} {
  153             template::head::add_javascript -src "/resources/richtext-ckeditor4/$suffix"
  154         } else {
  155             template::head::add_javascript -src "//cdn.ckeditor.com/$suffix"
  156             security::csp::require script-src cdn.ckeditor.com
  157             security::csp::require style-src cdn.ckeditor.com
  158             security::csp::require img-src cdn.ckeditor.com
  159         }
  160
  161         #
  162         # add required general directives for content security policies
  163         #
  164         security::csp::require script-src 'unsafe-eval'
  165         security::csp::require -force script-src 'unsafe-inline'
  166     }
  167    
  168     ad_proc ::richtext::ckeditor4::download {
  169         {-ck_package ""}
  170         {-version ""}
  171     } {
  172        
  173         Download the CKeditor package in the specified version and put
  174         it into a directory structure similar to the CDN structure to
  175         allow installation of multiple versions. When the local
  176         structure is available, it will be used by initialize_widget.
  177
  178         Notice, that for this automated download, the "unzip" program
  179         must be installed and $::acs::rootdir/packages/www must be
  180         writable by the web server.
  181        
  182     } {
  183         #
  184         # If no version or ck editor package are specified, use the
  185         # namespaced variables as default.
  186         #
  187         if {$version eq ""} {
  188             set version ${::richtext::ckeditor4::version}
  189         }
  190         if {$ck_package eq ""} {
  191             set ck_package ${::richtext::ckeditor4::ck_package}
  192         }
  193
  194         set download_url http://download.cksource.com/CKEditor/CKEditor/CKEditor%20${version}/ckeditor_${version}_${package}.zip
  195         set resources $::acs::rootdir/packages/richtext-ckeditor4/www/resources
  196
  197         #
  198         # Do we have unzip installed?
  199         #
  200         set unzip [::util::which unzip]
  201         if {$unzip eq ""} {
  202             error "can't install CKeditor locally; no unzip program found on PATH"
  203         }
  204        
  205         #
  206         # Do we have a writable output directory under resources?
  207         #
  208         if {![file isdirectory $resources/$version]} {
  209             file mkdir $resources/$version
  210         }
  211         if {![file writable $resources/$version]} {
  212             error "directory $resources/$version is not writable"
  213         }
  214
  215         #
  216         # So far, everything is fine, download the editor package
  217         #
  218         set result [util::http::get -url $download_url -spool]
  219         #ns_log notice "GOT $result"
  220         if {[dict get $result status] == 200} {
  221             #
  222             # The Download was successful, unzip it and let the
  223             # directory structure look similar as on the CDN.
  224             #
  225             set fn [dict get $result file]
  226             set output [exec $unzip -o $fn -d $resources/$version]
  227             file rename $resources/$version/ckeditor $resources/$version/$package
  228         } else {
  229             error "download of $download_url failed, HTTP status: [dict get $result status]"
  230         }
  231     }
  232
  233 }
  234
126 235 # Local variables:
127 236 #    mode: tcl
128 237 #    tcl-indent-level: 4
129 238 #    indent-tabs-mode: nil
130 239 # End: