From a03448ed97ebdc51583f26895d2e85ecb8d8e400 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Tue, 27 Aug 2019 18:51:55 +0800 Subject: [PATCH 01/21] =?UTF-8?q?=E9=99=84=E4=BB=B6=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E4=B8=8D=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/graduation_works_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/graduation_works_controller.rb b/app/controllers/graduation_works_controller.rb index a4a59a3f5..e9e07cc0d 100644 --- a/app/controllers/graduation_works_controller.rb +++ b/app/controllers/graduation_works_controller.rb @@ -274,7 +274,7 @@ class GraduationWorksController < ApplicationController @is_author = @work.user_id == current_user.id @work_members = @task.task_type == 1 ? [] : @task.graduation_works.where.not(user_id: @work.user_id). where(group_id: @work.group_id).includes(:user) - @attachments = @work.attachments.where.not(attachtype: 7) + @attachments = @work.attachments.where.not(attachtype: 7).or(attachtype: nil) end def comment_list From 815df50ad1f410756a66b533fe77b7fe78a77dc9 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Tue, 27 Aug 2019 18:54:47 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=E9=99=84=E4=BB=B6=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/graduation_works_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/graduation_works_controller.rb b/app/controllers/graduation_works_controller.rb index e9e07cc0d..204e0e5d4 100644 --- a/app/controllers/graduation_works_controller.rb +++ b/app/controllers/graduation_works_controller.rb @@ -274,7 +274,7 @@ class GraduationWorksController < ApplicationController @is_author = @work.user_id == current_user.id @work_members = @task.task_type == 1 ? [] : @task.graduation_works.where.not(user_id: @work.user_id). where(group_id: @work.group_id).includes(:user) - @attachments = @work.attachments.where.not(attachtype: 7).or(attachtype: nil) + @attachments = @work.attachments.where("attachtype != 7 or attachtype is null") end def comment_list From 8fc200a1cea6574c60caf8a6f9e0297b97112ec0 Mon Sep 17 00:00:00 2001 From: hjm <63528605@qq.com> Date: Wed, 28 Aug 2019 09:13:11 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=E5=8A=A0=E5=AE=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/courses/busyWork/CommonWorkPost.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/react/src/modules/courses/busyWork/CommonWorkPost.js b/public/react/src/modules/courses/busyWork/CommonWorkPost.js index 9de66ee5f..1859d6b70 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkPost.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkPost.js @@ -740,7 +740,7 @@ render(){
9 ? item.group_name : ''} >{item.group_name}
-
12 ? item.student_id : ''} >{item.student_id}
{item.commit_status===true?已提交 :""}
@@ -784,7 +784,7 @@ render(){
9 ? item.group_name : ''} >{item.group_name}
-
12 ? item.student_id : ''} >{item.student_id}
{item.user_id != this.props.current_user.user_id ? From 046a1e1551aaa71cf22d99251525760feebf967b Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Wed, 28 Aug 2019 09:20:24 +0800 Subject: [PATCH 04/21] =?UTF-8?q?=E5=88=86=E7=BB=84=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=E7=9A=84=E6=8F=90=E4=BA=A4=E4=BA=BA=E4=B8=8D=E8=83=BD=E5=8F=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/student_works_controller.rb | 10 ++++++---- app/models/student_work.rb | 1 + app/views/student_works/show.json.jbuilder | 3 ++- ...190828011222_add_update_user_id_to_student_works.rb | 6 ++++++ 4 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20190828011222_add_update_user_id_to_student_works.rb diff --git a/app/controllers/student_works_controller.rb b/app/controllers/student_works_controller.rb index b4677f4e3..f6872e533 100644 --- a/app/controllers/student_works_controller.rb +++ b/app/controllers/student_works_controller.rb @@ -92,6 +92,7 @@ class StudentWorksController < ApplicationController student_work.commit_time = Time.now student_work.update_time = Time.now student_work.commit_user_id = current_user.id + student_work.update_user_id = current_user.id student_work.group_id = @homework.homework_type == "group" ? @homework.max_group_id : 0 #提交作品时,计算是否迟交 @@ -112,7 +113,7 @@ class StudentWorksController < ApplicationController homework_common_id: @homework.id, project_id: student_work.project_id, late_penalty: student_work.late_penalty, work_status: student_work.work_status, commit_time: Time.now, update_time: Time.now, group_id: student_work.group_id, - commit_user_id: current_user.id) + commit_user_id: current_user.id, update_user_id: current_user.id) stu_work.save! student_work.attachments.each do |attachment| att = attachment.copy @@ -156,6 +157,7 @@ class StudentWorksController < ApplicationController begin @work.description = params[:description] @work.update_time = Time.now + @work.update_user_id = current_user.id # @work.commit_user_id = current_user.id if @work.save! Attachment.associate_container(params[:attachment_ids], @work.id, @work.class) @@ -172,7 +174,7 @@ class StudentWorksController < ApplicationController # 原成员更新描述、更新时间以及附件 @homework.student_works.where(group_id: @work.group_id, user_id: (work_user_ids & params_user_ids)).each do |work| # work.update_attributes(update_time: Time.now, description: @work.description, commit_user_id: current_user.id) - work.update_attributes(update_time: Time.now, description: @work.description) + work.update_attributes(update_time: Time.now, description: @work.description, update_user_id: current_user.id) work.attachments.destroy_all @work.attachments.each do |attachment| att = attachment.copy @@ -192,7 +194,7 @@ class StudentWorksController < ApplicationController @homework.student_works.where(group_id: @work.group_id, user_id: delete_user_ids). update_all(work_status: 0, description: nil, late_penalty: 0, commit_time: nil, update_time: nil, final_score: nil, teacher_score: nil, student_score: nil, teaching_asistant_score: nil, - work_score: nil, project_id: 0, group_id: 0, commit_user_id: nil) + work_score: nil, project_id: 0, group_id: 0, commit_user_id: nil, update_user_id: nil) # 新增加的成员 (params_user_ids - work_user_ids).each do |user_id| @@ -200,7 +202,7 @@ class StudentWorksController < ApplicationController stu_work.update_attributes(user_id: user_id, description: @work.description, homework_common_id: @homework.id, project_id: @work.project_id, late_penalty: @work.late_penalty, work_status: @work.work_status, commit_time: Time.now, update_time: Time.now, - group_id: @work.group_id, commit_user_id: @work.commit_user_id) + group_id: @work.group_id, commit_user_id: @work.commit_user_id, update_user_id: current_user.id) @work.attachments.each do |attachment| att = attachment.copy att.author_id = attachment.author_id diff --git a/app/models/student_work.rb b/app/models/student_work.rb index 074068273..168cfeb68 100644 --- a/app/models/student_work.rb +++ b/app/models/student_work.rb @@ -2,6 +2,7 @@ class StudentWork < ApplicationRecord #学生提交作品表 #work_status :0 未提交 1 已提交 2 迟交 belongs_to :user belongs_to :commit_user, class_name: 'User', foreign_key: :commit_user_id, optional: true + belongs_to :update_user, class_name: 'User', foreign_key: :update_user_id, optional: true belongs_to :homework_common belongs_to :myshixun, optional: true has_many :student_works_evaluation_distributions, dependent: :destroy diff --git a/app/views/student_works/show.json.jbuilder b/app/views/student_works/show.json.jbuilder index 5756ac9cb..192e4d8ec 100644 --- a/app/views/student_works/show.json.jbuilder +++ b/app/views/student_works/show.json.jbuilder @@ -5,7 +5,8 @@ json.is_evaluation @is_evaluation json.author_name @is_evaluation ? "匿名" : @work.user.real_name json.is_leader_work @work.user_id == @work.commit_user_id if @homework.homework_type == "group" json.is_author @is_author -json.update_user_name @is_evaluation ? "匿名" : @work.commit_user.try(:real_name) +json.commit_user_name @is_evaluation ? "匿名" : @work.commit_user.try(:real_name) +json.update_user_name @is_evaluation ? "匿名" : @work.update_user.try(:real_name) json.update_atta @homework.late_duration && @is_author diff --git a/db/migrate/20190828011222_add_update_user_id_to_student_works.rb b/db/migrate/20190828011222_add_update_user_id_to_student_works.rb new file mode 100644 index 000000000..c8e007998 --- /dev/null +++ b/db/migrate/20190828011222_add_update_user_id_to_student_works.rb @@ -0,0 +1,6 @@ +class AddUpdateUserIdToStudentWorks < ActiveRecord::Migration[5.2] + def change + add_column :student_works, :update_user_id, :integer + StudentWork.update_all("update_user_id = commit_user_id") + end +end From 904c017177d33c5bb1771bb7c5b6cad5953deaac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Wed, 28 Aug 2019 09:28:38 +0800 Subject: [PATCH 05/21] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/forums/MemoNew.js | 1673 ++++++++++---------- 1 file changed, 838 insertions(+), 835 deletions(-) diff --git a/public/react/src/modules/forums/MemoNew.js b/public/react/src/modules/forums/MemoNew.js index 11a3d0ca2..00a39b184 100644 --- a/public/react/src/modules/forums/MemoNew.js +++ b/public/react/src/modules/forums/MemoNew.js @@ -1,835 +1,838 @@ -import React, { Component } from 'react'; -import { Redirect } from 'react-router'; - -import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; - -import PropTypes from 'prop-types'; - -import classNames from 'classnames' - -import { Select,Icon, Upload, Button } from 'antd'; - -// demo http://react-component.github.io/upload/examples/simple.html -// import Upload from 'rc-upload'; - -import axios from 'axios' - -import 'antd/lib/select/style/index.css' -import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor' - -import { getUrl, getUploadActionUrl, appendFileSizeToUploadFileAll, appendFileSizeToUploadFile } from 'educoder' -const Option = Select.Option; -const $ = window.$; - -let origin = getUrl(); -let path = getUrl("/editormd/lib/") - -// load -if (!window.postUpMsg) { - $.getScript( - `${origin}/javascripts/attachments.js`, - (data, textStatus, jqxhr) => { - - }); -} - -// editorMD to create -/** - * - * @param id 渲染DOM的id - * @param width 宽度 - * @param high 高度 - * @param placeholder - * @param imageUrl 上传图片的url - * @returns {*} 返回一个editorMD实例 - */ -function create_editorMD(id, width, high, placeholder, imageUrl, callback){ - var editorName = window.editormd(id, { - width : width, - height : high, - syncScrolling : "single", - //你的lib目录的路径,我这边用JSP做测试的 - path : path , // "/editormd/lib/" - tex : true, - tocm : true, - emoji : true, - taskList : true, - codeFold : true, - searchReplace : true, - htmlDecode : "style,script,iframe", - sequenceDiagram : true, - autoFocus: false, - toolbarIcons : function() { - // Or return editormd.toolbarModes[name]; // full, simple, mini - // Using "||" set icons align right. - return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table" - // , '|', "underlineIcon" - , "|", "watch", "clear" ] - }, - toolbarCustomIcons : { - testIcon : "
", - testIcon1 : "
", - - // underlineIcon例子 - // underlineIcon : "
" - }, - //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 - saveHTMLToTextarea : true, - // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 - dialogMaskOpacity : 0.6, - placeholder: placeholder, - imageUpload : true, - imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], - imageUploadURL : imageUrl,//url - onload: function(){ - - // underlineIcon例子 - // $('#'+ id + " .underline").bind('click', function() { - // var __Cursor = editorName.cm.getDoc().getCursor(); - // editorName.appendMarkdown('__') - // editorName.cm.setCursor(__Cursor.line, __Cursor.ch + 2); - // }); - - // this.previewing(); - $("#"+ id +" [type=\"latex\"]").bind("click", function(){ - editorName.cm.replaceSelection("```latex"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("\n"); - editorName.cm.replaceSelection("```"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line-1, 0); - }); - - $("#"+ id +" [type=\"inline\"]").bind("click", function(){ - editorName.cm.replaceSelection("$$$$"); - var __Cursor = editorName.cm.getDoc().getCursor(); - editorName.cm.setCursor(__Cursor.line, __Cursor.ch-2); - editorName.cm.focus(); - }); - $("[type=\"inline\"]").attr("title", "行内公式"); - $("[type=\"latex\"]").attr("title", "多行公式"); - - window.md_elocalStorage(editorName, `memoNew_${id}`, "memoNew"); - - callback && callback() - } - }); - return editorName; -} - -const typeNameMap = { - '技术分享': 5, - '操作指南': 3, -} -export const typeNameMap2 = { - 5: '技术分享', - 3: '操作指南', -} -const defaultType = '技术分享' - -const languageSeparator = '/' -class MemoNew extends Component { - constructor(props) { - super(props) - this.mdRef = React.createRef(); - - // https://testbdweb.trustie.net/uploads.js?attachment_id=1&filename=jqui.js - // https://ant.design/components/upload-cn/ - this.uploaderProps = { - action: '/uploads.js', - data: { attachment_id: 1 }, // , filename: 2 - headers: { - Authorization: 'authorization-text', - }, - multiple: true, - beforeUpload(file) { - // console.log('beforeUpload', file.name); - }, - onStart: (file) => { - console.log('onStart', file.name); - // this.refs.inner.abort(file); - }, - onSuccess(file) { - console.log('onSuccess', file); - }, - onProgress(step, file) { - console.log('onProgress', Math.round(step.percent), file.name); - }, - onError(err) { - console.log('onError', err); - }, - }; - - this.state = { - memoSubject: '', - memoContent: '', - memoType: typeNameMap[defaultType], - memoRepertoire: '', - memoLanguage: [], - - repertoires: [], - currentSelectRepertoiresIndex: -1, - repertoiresTagMap: {}, - - fileList: [] - } - } - onCommit() { - const { memoSubject, memoRepertoire, memoLanguage, currentMemoId, memoType } = this.state; - const { showNotification } = this.props; - if (!memoSubject) { - showNotification('请先输入话题名称') - return - } - let mdVal; - try { - mdVal = this.mdRef.current.getValue() - - } catch (e) { - showNotification('编辑器还未加载完毕,请稍后') - return - } - - if (!mdVal) { - showNotification('请先输入话题内容') - return - } - // !memoRepertoire || - if (memoType === 5 && ( !memoLanguage || memoLanguage.length === 0 )) { - showNotification('请先选择技术标签') - return - } - /* - - - - http://localhost:3000/attachments/download/185790/Git-2.17.1.2-32-bit.exe - https://www.educoder.net/attachments/205112.js?attachment_id=1 - */ - // collect attachments - const $ = window.$; - const attachmentsMap = {}; - const attachmentIds = this.state.fileList.map(item => { - return item.response ? item.response.id : item.id - }) - // $('#attachments_fields .attachment').each(( index, item ) => { - // const filename = $(item).find('.upload_filename').val(); - // // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val() - // const token = $(item).find('input:nth-child(7)').val() - // const attachment_id = parseInt($(item).children().last().val()) - // attachmentsMap[index] = { - // filename, - // token, - // attachment_id - // } - // attachmentIds.push(attachment_id) - // }) - - - if (currentMemoId) { - this.updateMemo(attachmentIds) - } else { - this.newMemo(attachmentIds) - } - } - onCancel() { - const { currentMemoId, memoType } = this.state; - if (currentMemoId) { // 编辑 - this.props.history.push(`/forums/${currentMemoId}`) - } else { // 新建 - this.props.history.push(`/forums`) - } - // debugger;this.props.history.goBack() - } - updateMemo(attachmentsMap) { - const { memoSubject, memoRepertoire, memoLanguage, memoType, currentMemoId, content } = this.state; - const mdVal = this.mdRef.current.getValue() - console.log('isContentEdit: ', mdVal === content); - const newMemoUrl = `/memos/${currentMemoId}.json` - axios.put(newMemoUrl, { - content_changed: this.contentChanged, - tags: memoLanguage, - // memo:{ - subject: memoSubject , - content: mdVal, - forum_id: memoType, - repertoire_name: memoRepertoire, - // language: memoLanguage.join(languageSeparator), - // - // }, - attachment_ids: attachmentsMap - }, { - // withCredentials: true, - }) - .then((response) => { - const { status, message, memo_id } = response.data; - if (status === 0) { - window.$("html,body").animate({"scrollTop":0}) - this.props.history.push(`/forums/${currentMemoId}`) - } else { - this.props.showNotification(message) - } - }).catch((error) => { - console.log(error) - }) - } - newMemo(attachmentsMap) { - const { memoSubject, memoRepertoire, memoLanguage, memoType } = this.state; - const mdVal = this.mdRef.current.getValue() - - const newMemoUrl = `/memos.json` - axios.post(newMemoUrl, { - tags: memoLanguage, - // memo:{ - subject: memoSubject , - content: mdVal, - forum_id: memoType, - // repertoire_name: memoRepertoire, - - // }, - attachment_ids: attachmentsMap - }, { - // withCredentials: true, - }) - .then((response) => { - const { status, message, memo_id } = response.data; - if (status === 0) { - window.$("html,body").animate({"scrollTop":0}) - this.props.history.push(`/forums/${memo_id}`) - } else { - this.props.showNotification(message) - } - }).catch((error) => { - console.log(error) - }) - } - componentDidMount() { - const newMemoUrl = `/memos/new.json` - axios.get(newMemoUrl,{ - // withCredentials: true, - }) - .then((response) => { - const data = response.data; - const repertoires = []; - const repertoiresTagMap = {} - if ( data.tag_list ) { - // data.tag_list.forEach((item, index)=>{ - // const tagArray = []; - // item.tag.forEach( (tag, index) => { - // tagArray.push(tag.name) - // }) - // repertoires.push(item.rep.repertoire.name) - // repertoiresTagMap[item.rep.repertoire.name] = tagArray - // }) - this.setState({ - tag_list: data.tag_list - // repertoires, - // repertoiresTagMap - }) - - // const user = response.data.current_user; - // user.tidding_count = response.data.tidding_count; - // this.props.initCommonState(user) - - // 初始化 csrf meta - const $ = window.$ - $('head').append( $('') ) - $('head').append( $(``) ) - } - }).catch((error) => { - console.log(error) - }) - - // 如果是编辑 - const { match } = this.props - const memoId = match.params.memoId; - if (memoId) { - const memoUrl = `/memos/${match.params.memoId}/edit.json`; - axios.get(memoUrl,{ - // withCredentials: true, - }) - .then((response) => { - const tag_list = response.data.tag_list - if (tag_list) { - // this.setState({...response.data}) - const { content, forum_id, id, repertoire_name, subject, - current_user, tag_list, attachments_url, memo_tags, attachments } = response.data; - this.initMD(content); - // this.onRepertoiresChange(repertoire_name) - // tag -> memo_tags - const tag = memo_tags; - let memoLanguage = [] - if (tag) { - memoLanguage = tag.map((item, index) => { - return item.id + "" - }) - } - const fileList = attachments.map(item => { - return { - id: item.id, - uid: item.id, - name: appendFileSizeToUploadFile(item), - url: item.url, - filesize: item.filesize, - status: 'done' - } - }) - this.setState({ - fileList, - currentMemoId: memoId, - memoSubject: subject, - memoType: forum_id, - memoRepertoire: repertoire_name, - memoLanguage, - attachments_url, - content - - // repertoires: [], - // currentSelectRepertoiresIndex: -1, - }, ()=> { - // 解决有时候编辑时内容不显示的问题 - setTimeout(() => { - this.mdRef.current && this.mdRef.current.setValue(content || '') - }, 2000) - - $('.upload_filename').each((index, item) => { - var width = window._textWidth($(item), '14px'); - console.log(width) - $(item).css('width', width + 20) - }) - - }) - // 加载完后滚动条滚动 - window.$("html,body").animate({"scrollTop":0}) - - this.props.initForumState({ - // current_user, - tag_list - }) - } - - }).catch((error) => { - console.log(error) - }) - } else { - this.initMD(); - } - - - - - } - initMD(initValue) { - return; - - this.contentChanged = false; - const placeholder = ""; - // amp; - // 编辑时要传memoId - // const imageUrl = `/upload_with_markdown?container_id=&container_type=Memo`; - const imageUrl = `/api/attachments.json`; - - // 创建editorMd - - const taskpass_editormd = create_editorMD("memoMD", '100%', 400, placeholder, imageUrl, () => { - setTimeout(()=>{ - taskpass_editormd.resize() - taskpass_editormd.cm && taskpass_editormd.cm.refresh() - }, 500) - - if (initValue) { - taskpass_editormd.setValue(initValue) - } - taskpass_editormd.cm.on("change", (_cm, changeObj) =>{ - console.log('....contentChanged') - this.contentChanged = true; - }) - }); - this.taskpass_editormd = taskpass_editormd; - window.taskpass_editormd = taskpass_editormd; - - } - - renderOptions(array) { - const elementArray = []; - array.forEach(( item, index ) => { - elementArray.push( - - ) - }) - return elementArray - } - onRepertoiresChange(value) { - - const index = this.state.repertoires.indexOf(value) - - this.setState({ - currentSelectRepertoiresIndex: index, - memoRepertoire: value, - memoLanguage: '' - }); - }; - - renderTag() { - const { tag_list } = this.state; - if (!tag_list || tag_list.length === 0) { - return '' - } - const result = [] - - tag_list.forEach((item, index) => { - result.push() - }) - - return result; - } - - onTagChange(value) { - if (value && value.length > 3) { - this.props.showNotification(`最多选择3个技术标签`) - - return; - } - this.setState({ - memoLanguage: value - }) - } - - onTypeChange(value) { - - this.setState({ - memoType: typeNameMap[value] - }) - } - onMemoNameChange(e) { - this.setState({ - memoSubject: e.target.value - }) - } - renderAttachment() { - const { attachments_url } = this.state; - const attachments = [] - attachments_url.forEach((item, index) => { - const ar = item.url.split('/') - const fileName = ar[ar.length - 1] - /* -

- - {fileName} - -

- */ - // ?attachment_id=2 - /* - - - - */ - attachments.push( - - - - - - {window.conver_size(item.id)} - - - -
- {/**/} - -
-
-
- - ) - }) - return attachments; - } - handleChange = (info) => { - if (info.file.status === 'uploading' || info.file.status === 'done') { - let fileList = info.fileList; - this.setState({ - fileList: appendFileSizeToUploadFileAll(fileList) - }); - } - } - onAttachmentRemove = (file) => { - this.props.confirm({ - // title: '确定要删除这个附件吗?', - content: '是否确认删除?', - - okText: '确定', - cancelText: '取消', - // content: 'Some descriptions', - onOk: () => { - this.deleteAttachment(file) - }, - onCancel() { - console.log('Cancel'); - }, - }); - return false; - } - deleteAttachment = (file) => { - // 初次上传不能直接取uid - const url = `/attachments/${file.response ? file.response.id : file.uid}.json` - axios.delete(url, { - }) - .then((response) => { - if (response.data) { - const { status } = response.data; - if (status == 0) { - console.log('--- success') - - this.setState((state) => { - const index = state.fileList.indexOf(file); - const newFileList = state.fileList.slice(); - newFileList.splice(index, 1); - return { - fileList: newFileList, - }; - }); - } - } - }) - .catch(function (error) { - console.log(error); - }); - } - render() { - const { match, history } = this.props - const { - // repertoires, repertoiresTagMap, currentSelectRepertoiresIndex, memoRepertoire, - tag_list, - memoSubject, memoType, - memoLanguage, attachments_url, fileList } = this.state; - const memoId = match.params.memoId; - - const uploadProps = { - width: 600, - fileList, - multiple: true, - // https://github.com/ant-design/ant-design/issues/15505 - // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 - // showUploadList: false, - action: `${getUploadActionUrl()}`, - onChange: this.handleChange, - onRemove: this.onAttachmentRemove, - beforeUpload: (file) => { - console.log('beforeUpload', file.name); - const isLt150M = file.size / 1024 / 1024 < 150; - if (!isLt150M) { - this.props.showNotification('文件大小必须小于150MB!'); - } - return isLt150M; - }, - }; - return ( -
-
- { memoId ? '编辑话题' : '发布话题'} - {/* - */} -
- -
-
-

话题名称

-
- * -
- this.onMemoNameChange(val)} placeholder=""> - -
-
- - 必填项 - -
-
-
-
- -
-
-

内容

-
- * -
- - - {/*
- -
*/} -

-

-
-
- - 必填项 - -
-
- - - - {/*
- - { attachments_url && !!attachments_url.length && - this.renderAttachment() - } - - - {debugger;window.addInputFiles( window.$('.file_selector')[0] ) }} - style={{'display':'none'}} type="file"> - - -
*/} - - - {/*开始上传*/} - - - (单个文件150M以内) - - - {/* 请求status 422 */} - - {/* */} - {/*
- window.$('#_file').click()} - data-tip-down="请选择文件上传"> - - 上传附件 - (单个文件50M以内) - -
*/} -
-
- {/* TODOTODO 这里重复的html代码太多,如果有其他页面有类似需求,需要封装*/} - -
-
-

话题类型

-
- * -
- -
-
- - 必填项 - -
-
-
-
- - {/* memoType === typeNameMap['技术分享'] && -
-
-

技术标签

-
- * -
- -
-
- -
- -
- - 必填项 - -
-
-
-
*/} - - { memoType === typeNameMap['技术分享'] && -
-
-

技术标签

-
- * - -
- -
- -
- - 必填项 - -
-
-
-
} - -
- {this.onCommit()}}>提交 - { this.onCancel() }} className="defalutCancelbtn fl">取消 -
- -
- ); - } -} - -export default MemoNew; +import React, { Component } from 'react'; +import { Redirect } from 'react-router'; + +import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; + +import PropTypes from 'prop-types'; + +import classNames from 'classnames' + +import { Select,Icon, Upload, Button } from 'antd'; + +// demo http://react-component.github.io/upload/examples/simple.html +// import Upload from 'rc-upload'; + +import axios from 'axios' + +import 'antd/lib/select/style/index.css' +import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor' + +import { getUrl, getUploadActionUrl, appendFileSizeToUploadFileAll, appendFileSizeToUploadFile } from 'educoder' +const Option = Select.Option; +const $ = window.$; + +let origin = getUrl(); +let path = getUrl("/editormd/lib/") + +// load +if (!window.postUpMsg) { + $.getScript( + `${origin}/javascripts/attachments.js`, + (data, textStatus, jqxhr) => { + + }); +} + +// editorMD to create +/** + * + * @param id 渲染DOM的id + * @param width 宽度 + * @param high 高度 + * @param placeholder + * @param imageUrl 上传图片的url + * @returns {*} 返回一个editorMD实例 + */ +function create_editorMD(id, width, high, placeholder, imageUrl, callback){ + var editorName = window.editormd(id, { + width : width, + height : high, + syncScrolling : "single", + //你的lib目录的路径,我这边用JSP做测试的 + path : path , // "/editormd/lib/" + tex : true, + tocm : true, + emoji : true, + taskList : true, + codeFold : true, + searchReplace : true, + htmlDecode : "style,script,iframe", + sequenceDiagram : true, + autoFocus: false, + toolbarIcons : function() { + // Or return editormd.toolbarModes[name]; // full, simple, mini + // Using "||" set icons align right. + return ["bold", "italic", "|", "list-ul", "list-ol", "|", "code", "code-block", "|", "testIcon", "testIcon1", '|', "image", "table" + // , '|', "underlineIcon" + , "|", "watch", "clear" ] + }, + toolbarCustomIcons : { + testIcon : "
", + testIcon1 : "
", + + // underlineIcon例子 + // underlineIcon : "
" + }, + //这个配置在simple.html中并没有,但是为了能够提交表单,使用这个配置可以让构造出来的HTML代码直接在第二个隐藏的textarea域中,方便post提交表单。 + saveHTMLToTextarea : true, + // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 + dialogMaskOpacity : 0.6, + placeholder: placeholder, + imageUpload : true, + imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"], + imageUploadURL : imageUrl,//url + onload: function(){ + + // underlineIcon例子 + // $('#'+ id + " .underline").bind('click', function() { + // var __Cursor = editorName.cm.getDoc().getCursor(); + // editorName.appendMarkdown('__') + // editorName.cm.setCursor(__Cursor.line, __Cursor.ch + 2); + // }); + + // this.previewing(); + $("#"+ id +" [type=\"latex\"]").bind("click", function(){ + editorName.cm.replaceSelection("```latex"); + editorName.cm.replaceSelection("\n"); + editorName.cm.replaceSelection("\n"); + editorName.cm.replaceSelection("```"); + var __Cursor = editorName.cm.getDoc().getCursor(); + editorName.cm.setCursor(__Cursor.line-1, 0); + }); + + $("#"+ id +" [type=\"inline\"]").bind("click", function(){ + editorName.cm.replaceSelection("$$$$"); + var __Cursor = editorName.cm.getDoc().getCursor(); + editorName.cm.setCursor(__Cursor.line, __Cursor.ch-2); + editorName.cm.focus(); + }); + $("[type=\"inline\"]").attr("title", "行内公式"); + $("[type=\"latex\"]").attr("title", "多行公式"); + + window.md_elocalStorage(editorName, `memoNew_${id}`, "memoNew"); + + callback && callback() + } + }); + return editorName; +} + +const typeNameMap = { + '技术分享': 5, + '操作指南': 3, +} +export const typeNameMap2 = { + 5: '技术分享', + 3: '操作指南', +} +const defaultType = '技术分享' + +const languageSeparator = '/' +class MemoNew extends Component { + constructor(props) { + super(props) + this.mdRef = React.createRef(); + + // https://testbdweb.trustie.net/uploads.js?attachment_id=1&filename=jqui.js + // https://ant.design/components/upload-cn/ + this.uploaderProps = { + action: '/uploads.js', + data: { attachment_id: 1 }, // , filename: 2 + headers: { + Authorization: 'authorization-text', + }, + multiple: true, + beforeUpload(file) { + // console.log('beforeUpload', file.name); + }, + onStart: (file) => { + console.log('onStart', file.name); + // this.refs.inner.abort(file); + }, + onSuccess(file) { + console.log('onSuccess', file); + }, + onProgress(step, file) { + console.log('onProgress', Math.round(step.percent), file.name); + }, + onError(err) { + console.log('onError', err); + }, + }; + + this.state = { + memoSubject: '', + memoContent: '', + memoType: typeNameMap[defaultType], + memoRepertoire: '', + memoLanguage: [], + + repertoires: [], + currentSelectRepertoiresIndex: -1, + repertoiresTagMap: {}, + + fileList: [] + } + } + onCommit() { + const { memoSubject, memoRepertoire, memoLanguage, currentMemoId, memoType } = this.state; + const { showNotification } = this.props; + if (!memoSubject) { + showNotification('请先输入话题名称') + return + } + let mdVal; + try { + mdVal = this.mdRef.current.getValue() + + } catch (e) { + showNotification('编辑器还未加载完毕,请稍后') + return + } + + if (!mdVal) { + showNotification('请先输入话题内容') + return + } + // !memoRepertoire || + if (memoType === 5 && ( !memoLanguage || memoLanguage.length === 0 )) { + showNotification('请先选择技术标签') + return + } + /* + + + + http://localhost:3000/attachments/download/185790/Git-2.17.1.2-32-bit.exe + https://www.educoder.net/attachments/205112.js?attachment_id=1 + */ + // collect attachments + const $ = window.$; + const attachmentsMap = {}; + const attachmentIds = this.state.fileList.map(item => { + return item.response ? item.response.id : item.id + }) + // $('#attachments_fields .attachment').each(( index, item ) => { + // const filename = $(item).find('.upload_filename').val(); + // // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val() + // const token = $(item).find('input:nth-child(7)').val() + // const attachment_id = parseInt($(item).children().last().val()) + // attachmentsMap[index] = { + // filename, + // token, + // attachment_id + // } + // attachmentIds.push(attachment_id) + // }) + + + if (currentMemoId) { + this.updateMemo(attachmentIds) + } else { + this.newMemo(attachmentIds) + } + } + onCancel() { + const { currentMemoId, memoType } = this.state; + if (currentMemoId) { // 编辑 + this.props.history.push(`/forums/${currentMemoId}`) + } else { // 新建 + this.props.history.push(`/forums`) + } + // debugger;this.props.history.goBack() + } + updateMemo(attachmentsMap) { + const { memoSubject, memoRepertoire, memoLanguage, memoType, currentMemoId, content } = this.state; + const mdVal = this.mdRef.current.getValue() + console.log('isContentEdit: ', mdVal === content); + const newMemoUrl = `/memos/${currentMemoId}.json` + axios.put(newMemoUrl, { + content_changed: this.contentChanged, + tags: memoLanguage, + // memo:{ + subject: memoSubject , + content: mdVal, + forum_id: memoType, + repertoire_name: memoRepertoire, + // language: memoLanguage.join(languageSeparator), + // + // }, + attachment_ids: attachmentsMap + }, { + // withCredentials: true, + }) + .then((response) => { + const { status, message, memo_id } = response.data; + if (status === 0) { + window.$("html,body").animate({"scrollTop":0}) + this.props.history.push(`/forums/${currentMemoId}`) + } else { + this.props.showNotification(message) + } + }).catch((error) => { + console.log(error) + }) + } + newMemo(attachmentsMap) { + const { memoSubject, memoRepertoire, memoLanguage, memoType } = this.state; + const mdVal = this.mdRef.current.getValue() + + const newMemoUrl = `/memos.json` + axios.post(newMemoUrl, { + tags: memoLanguage, + // memo:{ + subject: memoSubject , + content: mdVal, + forum_id: memoType, + // repertoire_name: memoRepertoire, + + // }, + attachment_ids: attachmentsMap + }, { + // withCredentials: true, + }) + .then((response) => { + const { status, message, memo_id } = response.data; + if (status === 0) { + window.$("html,body").animate({"scrollTop":0}) + this.props.history.push(`/forums/${memo_id}`) + } else { + this.props.showNotification(message) + } + }).catch((error) => { + console.log(error) + }) + } + componentDidMount() { + const newMemoUrl = `/memos/new.json` + axios.get(newMemoUrl,{ + // withCredentials: true, + }) + .then((response) => { + const data = response.data; + const repertoires = []; + const repertoiresTagMap = {} + if ( data.tag_list ) { + // data.tag_list.forEach((item, index)=>{ + // const tagArray = []; + // item.tag.forEach( (tag, index) => { + // tagArray.push(tag.name) + // }) + // repertoires.push(item.rep.repertoire.name) + // repertoiresTagMap[item.rep.repertoire.name] = tagArray + // }) + this.setState({ + tag_list: data.tag_list + // repertoires, + // repertoiresTagMap + }) + + // const user = response.data.current_user; + // user.tidding_count = response.data.tidding_count; + // this.props.initCommonState(user) + + // 初始化 csrf meta + const $ = window.$ + $('head').append( $('') ) + $('head').append( $(``) ) + } + }).catch((error) => { + console.log(error) + }) + + // 如果是编辑 + const { match } = this.props + const memoId = match.params.memoId; + if (memoId) { + const memoUrl = `/memos/${match.params.memoId}/edit.json`; + axios.get(memoUrl,{ + // withCredentials: true, + }) + .then((response) => { + const tag_list = response.data.tag_list + if (tag_list) { + // this.setState({...response.data}) + const { content, forum_id, id, repertoire_name, subject, + current_user, tag_list, attachments_url, memo_tags, attachments } = response.data; + this.initMD(content); + // this.onRepertoiresChange(repertoire_name) + // tag -> memo_tags + const tag = memo_tags; + let memoLanguage = [] + if (tag) { + memoLanguage = tag.map((item, index) => { + return item.id + "" + }) + } + const fileList = attachments.map(item => { + return { + id: item.id, + uid: item.id, + name: appendFileSizeToUploadFile(item), + url: item.url, + filesize: item.filesize, + status: 'done' + } + }) + this.setState({ + fileList, + currentMemoId: memoId, + memoSubject: subject, + memoType: forum_id, + memoRepertoire: repertoire_name, + memoLanguage, + attachments_url, + content + + // repertoires: [], + // currentSelectRepertoiresIndex: -1, + }, ()=> { + // 解决有时候编辑时内容不显示的问题 + setTimeout(() => { + this.mdRef.current && this.mdRef.current.setValue(content || '') + }, 2000) + + $('.upload_filename').each((index, item) => { + var width = window._textWidth($(item), '14px'); + console.log(width) + $(item).css('width', width + 20) + }) + + }) + // 加载完后滚动条滚动 + window.$("html,body").animate({"scrollTop":0}) + + this.props.initForumState({ + // current_user, + tag_list + }) + } + + }).catch((error) => { + console.log(error) + }) + } else { + this.initMD(); + } + + + + + } + initMD(initValue) { + return; + + this.contentChanged = false; + const placeholder = ""; + // amp; + // 编辑时要传memoId + // const imageUrl = `/upload_with_markdown?container_id=&container_type=Memo`; + const imageUrl = `/api/attachments.json`; + + // 创建editorMd + + const taskpass_editormd = create_editorMD("memoMD", '100%', 400, placeholder, imageUrl, () => { + setTimeout(()=>{ + taskpass_editormd.resize() + taskpass_editormd.cm && taskpass_editormd.cm.refresh() + }, 500) + + if (initValue) { + taskpass_editormd.setValue(initValue) + } + taskpass_editormd.cm.on("change", (_cm, changeObj) =>{ + console.log('....contentChanged') + this.contentChanged = true; + }) + }); + this.taskpass_editormd = taskpass_editormd; + window.taskpass_editormd = taskpass_editormd; + + } + + renderOptions(array) { + const elementArray = []; + array.forEach(( item, index ) => { + elementArray.push( + + ) + }) + return elementArray + } + onRepertoiresChange(value) { + + const index = this.state.repertoires.indexOf(value) + + this.setState({ + currentSelectRepertoiresIndex: index, + memoRepertoire: value, + memoLanguage: '' + }); + }; + + renderTag() { + const { tag_list } = this.state; + if (!tag_list || tag_list.length === 0) { + return '' + } + const result = [] + + tag_list.forEach((item, index) => { + result.push() + }) + + return result; + } + + onTagChange(value) { + if (value && value.length > 3) { + this.props.showNotification(`最多选择3个技术标签`) + + return; + } + this.setState({ + memoLanguage: value + }) + } + + onTypeChange(value) { + + this.setState({ + memoType: typeNameMap[value] + }) + } + onMemoNameChange(e) { + this.setState({ + memoSubject: e.target.value + }) + } + renderAttachment() { + const { attachments_url } = this.state; + const attachments = [] + attachments_url.forEach((item, index) => { + const ar = item.url.split('/') + const fileName = ar[ar.length - 1] + /* +

+ + {fileName} + +

+ */ + // ?attachment_id=2 + /* + + + + */ + attachments.push( + + + + + + {window.conver_size(item.id)} + + + +
+ {/**/} + +
+
+
+ + ) + }) + return attachments; + } + handleChange = (info) => { + if (info.file.status === 'uploading' || info.file.status === 'done') { + let fileList = info.fileList; + this.setState({ + fileList: appendFileSizeToUploadFileAll(fileList) + }); + } + } + onAttachmentRemove = (file) => { + this.props.confirm({ + // title: '确定要删除这个附件吗?', + content: '是否确认删除?', + + okText: '确定', + cancelText: '取消', + // content: 'Some descriptions', + onOk: () => { + this.deleteAttachment(file) + }, + onCancel() { + console.log('Cancel'); + }, + }); + return false; + } + deleteAttachment = (file) => { + // 初次上传不能直接取uid + const url = `/attachments/${file.response ? file.response.id : file.uid}.json` + axios.delete(url, { + }) + .then((response) => { + if (response.data) { + const { status } = response.data; + if (status == 0) { + console.log('--- success') + + this.setState((state) => { + const index = state.fileList.indexOf(file); + const newFileList = state.fileList.slice(); + newFileList.splice(index, 1); + return { + fileList: newFileList, + }; + }); + } + } + }) + .catch(function (error) { + console.log(error); + }); + } + render() { + const { match, history } = this.props + const { + // repertoires, repertoiresTagMap, currentSelectRepertoiresIndex, memoRepertoire, + tag_list, + memoSubject, memoType, + memoLanguage, attachments_url, fileList } = this.state; + const memoId = match.params.memoId; + + const uploadProps = { + width: 600, + fileList, + multiple: true, + // https://github.com/ant-design/ant-design/issues/15505 + // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 + // showUploadList: false, + action: `${getUploadActionUrl()}`, + onChange: this.handleChange, + onRemove: this.onAttachmentRemove, + beforeUpload: (file) => { + console.log('beforeUpload', file.name); + const isLt150M = file.size / 1024 / 1024 < 150; + if (!isLt150M) { + this.props.showNotification('文件大小必须小于150MB!'); + } + return isLt150M; + }, + }; + return ( +
+

交流问答 / 详情

+
+ { memoId ? '编辑话题' : '发布话题'} + {/* + */} +
+ +
+
+

话题名称

+
+ * +
+ this.onMemoNameChange(val)} placeholder=""> + +
+
+ + 必填项 + +
+
+
+
+ +
+
+

内容

+
+ * +
+ + + {/*
+ +
*/} +

+

+
+
+ + 必填项 + +
+
+ + + + {/*
+ + { attachments_url && !!attachments_url.length && + this.renderAttachment() + } + + + {debugger;window.addInputFiles( window.$('.file_selector')[0] ) }} + style={{'display':'none'}} type="file"> + + +
*/} + + + {/*开始上传*/} + + + (单个文件150M以内) + + + {/* 请求status 422 */} + + {/* */} + {/*
+ window.$('#_file').click()} + data-tip-down="请选择文件上传"> + + 上传附件 + (单个文件50M以内) + +
*/} +
+
+ {/* TODOTODO 这里重复的html代码太多,如果有其他页面有类似需求,需要封装*/} + +
+
+

话题类型

+
+ * +
+ +
+
+ + 必填项 + +
+
+
+
+ + {/* memoType === typeNameMap['技术分享'] && +
+
+

技术标签

+
+ * +
+ +
+
+ +
+ +
+ + 必填项 + +
+
+
+
*/} + + { memoType === typeNameMap['技术分享'] && +
+
+

技术标签

+
+ * + +
+ +
+ +
+ + 必填项 + +
+
+
+
} + +
+ {this.onCommit()}}>提交 + { this.onCancel() }} className="defalutCancelbtn fl">取消 +
+ +
+ ); + } +} + +export default MemoNew; From 2266857dac9f9eec403d0c82f84539b748948cc6 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Wed, 28 Aug 2019 09:29:04 +0800 Subject: [PATCH 06/21] =?UTF-8?q?=E8=B5=84=E6=BA=90=E7=9A=84=E5=8F=91?= =?UTF-8?q?=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/files_controller.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index a6eafe0f3..791d145c2 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -172,17 +172,17 @@ class FilesController < ApplicationController attachment_ids.each do |attachment_id| ori = Attachment.find_by_id(attachment_id) # 同一个资源可以多次发送到课堂 - @course.attachments.each do |att| - @exist = false - if att.id == ori.id || (!att.copy_from.nil? && !ori.copy_from.nil? && att.copy_from == ori.copy_from) || att.copy_from == ori.id || att.id == ori.copy_from - att.created_on = Time.now - att.save - @exist = true - break - end - end - - next if @exist + # @course.attachments.each do |att| + # @exist = false + # if att.id == ori.id || (!att.copy_from.nil? && !ori.copy_from.nil? && att.copy_from == ori.copy_from) || att.copy_from == ori.id || att.id == ori.copy_from + # att.created_on = Time.now + # att.save + # @exist = true + # break + # end + # end + # + # next if @exist attach_copied_obj = ori.copy attach_copied_obj.container = @course attach_copied_obj.created_on = Time.now From 053a54f9035733e2721828be5d3c0ed1b6de87b7 Mon Sep 17 00:00:00 2001 From: hjm <63528605@qq.com> Date: Wed, 28 Aug 2019 09:38:13 +0800 Subject: [PATCH 07/21] commit_user_name --- .../react/src/modules/courses/busyWork/CommonWorkAppraise.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js b/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js index f29204563..d1e271981 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkAppraise.js @@ -162,7 +162,7 @@ class CommonWorkAppraise extends Component{ let {course_name, homework_name, search, page, loadingstate, homework_status, reference_answer, attachments, homework_id, project_info, work_members, is_evaluation, - description, update_user_name, update_time, commit_time, author_name, + description, update_user_name, commit_user_name, update_time, commit_time, author_name, revise_attachments, revise_reason, atta_update_user, atta_update_time, atta_update_user_login, Modalstype,Modalstopval,ModalCancel,ModalSave,loadtype, is_leader_work } =this.state; @@ -237,7 +237,7 @@ class CommonWorkAppraise extends Component{ { commit_time && 提交 - {author_name} + {commit_user_name} {moment(commit_time).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(commit_time).format('YYYY-MM-DD HH:mm')} From d040850a3a4aa032222a4e027c7e78f249f9bd80 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Wed, 28 Aug 2019 09:41:11 +0800 Subject: [PATCH 08/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=8F=82=E8=80=83?= =?UTF-8?q?=E7=AD=94=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/challenges_controller.rb | 23 +++++++++++-------- .../challenges/crud_answer.json.jbuilder | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/controllers/challenges_controller.rb b/app/controllers/challenges_controller.rb index 0f6532372..48ba77b0c 100644 --- a/app/controllers/challenges_controller.rb +++ b/app/controllers/challenges_controller.rb @@ -234,18 +234,21 @@ class ChallengesController < ApplicationController # {...}, ...] #} def crud_answer - raise '参考答案不能为空' if params[:challenge_answer].empty? - raise '占比之和必须为100%' if params[:challenge_answer].map{|a| a[:score]}.sum != 100 - ActiveRecord::Base.transaction do - @challenge.challenge_answers.destroy_all if @challenge.challenge_answers - params[:challenge_answer].each_with_index do |answer, index| - # 内容为空不保存 - next if answer[:contents].blank? - ChallengeAnswer.create(name: answer[:name], contents: answer[:contents], - level: index+1, score: answer[:score], challenge_id: @challenge.id) + if @challenge.challenge_answers && params[:challenge_answer].empty? + @challenge.challenge_answers.destroy_all + else + raise '参考答案不能为空' if params[:challenge_answer].empty? + raise '占比之和必须为100%' if params[:challenge_answer].map{|a| a[:score]}.sum != 100 + ActiveRecord::Base.transaction do + @challenge.challenge_answers.destroy_all if @challenge.challenge_answers + params[:challenge_answer].each_with_index do |answer, index| + # 内容为空不保存 + next if answer[:contents].blank? + ChallengeAnswer.create(name: answer[:name], contents: answer[:contents], + level: index+1, score: answer[:score], challenge_id: @challenge.id) + end end end - end # 查看参考答案接口 diff --git a/app/views/challenges/crud_answer.json.jbuilder b/app/views/challenges/crud_answer.json.jbuilder index b11268d99..e16f09423 100644 --- a/app/views/challenges/crud_answer.json.jbuilder +++ b/app/views/challenges/crud_answer.json.jbuilder @@ -1,2 +1,2 @@ json.status 1 -json.message "创建参考答案成功" \ No newline at end of file +json.message "操作成功" \ No newline at end of file From 7b988654cb9a70adf7e981b5a5a9ebe2053c7e15 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Wed, 28 Aug 2019 09:45:44 +0800 Subject: [PATCH 09/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/challenges_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/challenges_controller.rb b/app/controllers/challenges_controller.rb index 48ba77b0c..8cb68b1d4 100644 --- a/app/controllers/challenges_controller.rb +++ b/app/controllers/challenges_controller.rb @@ -234,7 +234,7 @@ class ChallengesController < ApplicationController # {...}, ...] #} def crud_answer - if @challenge.challenge_answers && params[:challenge_answer].empty? + if @challenge.challenge_answers && params[:challenge_answer].blank? @challenge.challenge_answers.destroy_all else raise '参考答案不能为空' if params[:challenge_answer].empty? From 30bc2a03dc1260580ca16e46511353ab9bbeab3f Mon Sep 17 00:00:00 2001 From: hjm <63528605@qq.com> Date: Wed, 28 Aug 2019 09:52:41 +0800 Subject: [PATCH 10/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=AD=94=E6=A1=88=20?= =?UTF-8?q?=E6=9C=AA=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/tpm/challengesnew/TPManswer2.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/react/src/modules/tpm/challengesnew/TPManswer2.js b/public/react/src/modules/tpm/challengesnew/TPManswer2.js index 6218cc468..19765597e 100644 --- a/public/react/src/modules/tpm/challengesnew/TPManswer2.js +++ b/public/react/src/modules/tpm/challengesnew/TPManswer2.js @@ -120,7 +120,9 @@ export default class TPManswer extends Component { let urlAnswer = `/shixuns/${id}/challenges/${checkpointId}/answer.json`; axios.get(urlAnswer).then((response) => { - if (response.data) { + if (response.data.status === 401) { + + } else if (response.data) { this.setState({ answers: response.data }) } }) @@ -158,7 +160,7 @@ export default class TPManswer extends Component { if (!isValidate) { return; } - if (totalScore != 100) { + if (answersParams.length != 0 && totalScore != 100) { this.props.showSnackbar("请先保证占比和为100%"); return; } From be7dfb8f69b6377388357c787c20d7a0e8955540 Mon Sep 17 00:00:00 2001 From: hjm <63528605@qq.com> Date: Wed, 28 Aug 2019 10:04:18 +0800 Subject: [PATCH 11/21] =?UTF-8?q?=E5=85=B3=E5=8D=A1=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E7=9A=84=E8=AF=B4=E6=98=8E=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/page/component/TPICodeSetting.js | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/public/react/src/modules/page/component/TPICodeSetting.js b/public/react/src/modules/page/component/TPICodeSetting.js index c83422c4e..05caa145b 100644 --- a/public/react/src/modules/page/component/TPICodeSetting.js +++ b/public/react/src/modules/page/component/TPICodeSetting.js @@ -116,20 +116,40 @@ class TPICodeSetting extends Component {
代码补全
*/}
-
CTRL + S
-
保存代码
+
保存代码
+
Ctrl + S
+
+
+
唤出快捷键列表
+
F1 / Alt + F1
+
+
+
左右缩进
+
Ctrl + ]/[
+
+
+
跳到匹配的括号
+
Ctrl + Shift + \
+
+
+
转到行首
+
Home
+
+
+
转到行尾
+
End

- 学员使用说明 + 关卡配置信息 {/* */}

跳关
-
{ task_pass ? 'on' : 'off'}
+
{ task_pass ? '允许' : '不允许'}
@@ -137,7 +157,7 @@ class TPICodeSetting extends Component { : "禁止学员通过金币解锁查看测试集内容"} disableFocusListener={true}>
测试集解锁
-
{ test_set_permission ? 'on' : 'off'}
+
{ test_set_permission ? '允许' : '不允许'}
@@ -145,15 +165,15 @@ class TPICodeSetting extends Component { : "启用页面复制和粘贴功能"} disableFocusListener={true}>
-
禁止代码复制粘贴
-
{ forbid_copy ? 'on' : 'off'}
+
代码复制粘贴
+
{ !forbid_copy ? '允许' : '不允许'}
- -

+ + {/* */} + {/*

说明 - {/* */}

@@ -161,7 +181,7 @@ class TPICodeSetting extends Component { 本编辑器和Visual Studio Code的快捷键一致,使用F1或Alt+F1 (Internet Explorer)可以唤出快捷键列表。
- + */} From 95f92dd28486e816d5d01e45216c234591d4977a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Wed, 28 Aug 2019 10:14:52 +0800 Subject: [PATCH 12/21] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=AF=BE=E5=A0=82?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/courses/Resource/index.js | 29 ++++++++++--------- .../courses/shixunHomework/shixunHomework.js | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/public/react/src/modules/courses/Resource/index.js b/public/react/src/modules/courses/Resource/index.js index a0ba1e8da..1565f5abb 100644 --- a/public/react/src/modules/courses/Resource/index.js +++ b/public/react/src/modules/courses/Resource/index.js @@ -119,20 +119,21 @@ class Fileslists extends Component{ }).then((response) => { if(response!=undefined){ - if(response.data&&response.data){ - let list=response.data.course_modules; - let course_second_categoriess; - list.map((item,key)=>{ - course_second_categoriess=item.course_second_categories - }) - - this.setState({ - course_modules:response.data, - has_course_groups:response.data.has_course_groups, - course_second_categories:course_second_categoriess - }) - } - + if(response.data&&response.data) { + if (response.data.status != 401) { + let list = response.data.course_modules; + let course_second_categoriess; + list.map((item, key) => { + course_second_categoriess = item.course_second_categories + }) + + this.setState({ + course_modules: response.data, + has_course_groups: response.data.has_course_groups, + course_second_categories: course_second_categoriess + }) + } + } } diff --git a/public/react/src/modules/courses/shixunHomework/shixunHomework.js b/public/react/src/modules/courses/shixunHomework/shixunHomework.js index c7fa2e70a..88dffa232 100644 --- a/public/react/src/modules/courses/shixunHomework/shixunHomework.js +++ b/public/react/src/modules/courses/shixunHomework/shixunHomework.js @@ -1210,7 +1210,7 @@ class ShixunHomework extends Component{ { - datas===undefined?'' :datas.homeworks.length===0? :"" + datas===undefined?"":datas.homeworks && datas.homeworks.length===0? :"" } From 41ba5a36d5c1fe01dedb6b8d867b76179d4faf6d Mon Sep 17 00:00:00 2001 From: p31729568 Date: Wed, 28 Aug 2019 10:17:24 +0800 Subject: [PATCH 13/21] admins: mirror script manage --- app/assets/javascripts/admin.js | 8 + .../javascripts/admins/mirror_scripts/form.js | 33 + app/assets/stylesheets/admin.scss | 1 + app/assets/stylesheets/admins/common.scss | 4 + .../admins/mirror_repositories_controller.rb | 1 + .../admins/mirror_scripts_controller.rb | 59 + .../concerns/admins/render_helper.rb | 2 +- .../mirror_repositories/shared/_list.html.erb | 4 +- app/views/admins/mirror_scripts/edit.html.erb | 8 + .../admins/mirror_scripts/index.html.erb | 14 + app/views/admins/mirror_scripts/new.html.erb | 8 + .../mirror_scripts/shared/_form.html.erb | 12 + .../mirror_scripts/shared/_list.html.erb | 32 + app/views/admins/shared/403.html.erb | 6 + config/admins/sidebar.yml | 2 +- config/initializers/assets.rb | 2 + config/routes.rb | 2 + ...fest-1c370772f16743f825981ab0e5c94237.json | 2 +- ...fa3e736bbcebed51b503ea9972221022adb6b.css} | 628 +- ...e736bbcebed51b503ea9972221022adb6b.css.gz} | Bin 49647 -> 52169 bytes ...6ce92b8971eb5b78bd885db0dc99c73c4d3773.js} | 9958 +++++++++++++++++ ...92b8971eb5b78bd885db0dc99c73c4d3773.js.gz} | Bin 219999 -> 325964 bytes ...971fae73f23e39cee0ed1464e007bd016a376.css} | 633 +- ...1fae73f23e39cee0ed1464e007bd016a376.css.gz | Bin 0 -> 89207 bytes ...47dca1a74fa0a1c423fffd5def99c386e17.css.gz | Bin 86711 -> 0 bytes ...2e08889343ad253b5847d446cee9620b2f51f0.js} | 9958 +++++++++++++++++ ...8889343ad253b5847d446cee9620b2f51f0.js.gz} | Bin 257033 -> 363116 bytes vendor/assets/codemirror/lib/codemirror.css | 349 + vendor/assets/codemirror/lib/codemirror.js | 9765 ++++++++++++++++ vendor/assets/codemirror/mode/shell/shell.js | 152 + 30 files changed, 31616 insertions(+), 27 deletions(-) create mode 100644 app/assets/javascripts/admins/mirror_scripts/form.js create mode 100644 app/controllers/admins/mirror_scripts_controller.rb create mode 100644 app/views/admins/mirror_scripts/edit.html.erb create mode 100644 app/views/admins/mirror_scripts/index.html.erb create mode 100644 app/views/admins/mirror_scripts/new.html.erb create mode 100644 app/views/admins/mirror_scripts/shared/_form.html.erb create mode 100644 app/views/admins/mirror_scripts/shared/_list.html.erb create mode 100644 app/views/admins/shared/403.html.erb rename public/assets/{admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css => admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css} (97%) rename public/assets/{admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css.gz => admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css.gz} (57%) rename public/assets/{admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js => admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js} (69%) rename public/assets/{admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js.gz => admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js.gz} (63%) rename public/assets/{application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css => application-378235e0207ed9f59fd6201c7b0971fae73f23e39cee0ed1464e007bd016a376.css} (98%) create mode 100644 public/assets/application-378235e0207ed9f59fd6201c7b0971fae73f23e39cee0ed1464e007bd016a376.css.gz delete mode 100644 public/assets/application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css.gz rename public/assets/{application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js => application-a044d1142b1e21bfda21aab2e22e08889343ad253b5847d446cee9620b2f51f0.js} (72%) rename public/assets/{application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js.gz => application-a044d1142b1e21bfda21aab2e22e08889343ad253b5847d446cee9620b2f51f0.js.gz} (57%) create mode 100644 vendor/assets/codemirror/lib/codemirror.css create mode 100644 vendor/assets/codemirror/lib/codemirror.js create mode 100644 vendor/assets/codemirror/mode/shell/shell.js diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index 196404300..7d1908547 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -13,6 +13,9 @@ //= require bootstrap-datepicker //= require bootstrap.viewer +//= require lib/codemirror +//= require mode/shell/shell + //= require_tree ./i18n //= require_tree ./admins @@ -40,6 +43,11 @@ $(document).on('turbolinks:load', function(){ } }); +$(document).on("turbolinks:before-cache", function () { + $('[data-toggle="tooltip"]').tooltip('hide'); + $('[data-toggle="popover"]').popover('hide'); +}); + // var progressBar = new Turbolinks.ProgressBar(); // $(document).on('ajax:send', function(event){ diff --git a/app/assets/javascripts/admins/mirror_scripts/form.js b/app/assets/javascripts/admins/mirror_scripts/form.js new file mode 100644 index 000000000..3aa318d8d --- /dev/null +++ b/app/assets/javascripts/admins/mirror_scripts/form.js @@ -0,0 +1,33 @@ +$(document).on('turbolinks:load', function() { + if ($('body.admins-mirror-scripts-edit-page, body.admins-mirror-scripts-update-page, body.admins-mirror-scripts-new-page, body.admins-mirror-scripts-create-page').length > 0) { + var $form = $('form.script-form'); + + // codemirror编辑器 + var scriptEditor = CodeMirror.fromTextArea(document.getElementById('mirror_script_script'), { + lineNumbers: true, + mode: 'shell', + theme: "default", + indentUnit: 4, //代码缩进为一个tab的距离 + matchBrackets: true, + autoRefresh: true, + smartIndent: true,//智能换行 + styleActiveLine: true, + lint: true + }); + scriptEditor.setSize('auto', '600px'); + + $form.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + "mirror_script[script_type]": { + required: true + } + } + }); + + $form.submit(function(e){ + if(!$form.valid()){ e.preventDefault(); } + }); + } +}); \ No newline at end of file diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 36f1e537f..7710423ea 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -5,6 +5,7 @@ @import "select2-bootstrap4.min"; @import "bootstrap-datepicker"; @import "bootstrap-datepicker.standalone"; +@import "lib/codemirror"; @import "admins/*"; diff --git a/app/assets/stylesheets/admins/common.scss b/app/assets/stylesheets/admins/common.scss index 2254166fd..56b286981 100644 --- a/app/assets/stylesheets/admins/common.scss +++ b/app/assets/stylesheets/admins/common.scss @@ -106,5 +106,9 @@ padding: 0.5rem 2rem; } } + + .CodeMirror { + border: 1px solid #ced4da; + } } diff --git a/app/controllers/admins/mirror_repositories_controller.rb b/app/controllers/admins/mirror_repositories_controller.rb index 63e4667d1..aed8dc09e 100644 --- a/app/controllers/admins/mirror_repositories_controller.rb +++ b/app/controllers/admins/mirror_repositories_controller.rb @@ -87,6 +87,7 @@ class Admins::MirrorRepositoriesController < Admins::BaseController end def check_shixun_mirrors! + return return unless request.format.html? Admins::CheckShixunMirrorsService.call diff --git a/app/controllers/admins/mirror_scripts_controller.rb b/app/controllers/admins/mirror_scripts_controller.rb new file mode 100644 index 000000000..9ed3611f4 --- /dev/null +++ b/app/controllers/admins/mirror_scripts_controller.rb @@ -0,0 +1,59 @@ +class Admins::MirrorScriptsController < Admins::BaseController + helper_method :current_mirror + + def index + scripts = current_mirror.mirror_scripts.order(updated_at: :desc) + @scripts = paginate scripts + end + + def new + @script = current_mirror.mirror_scripts.new + end + + def create + @script = current_mirror.mirror_scripts.new(form_params) + + if @script.save + flash[:success] = '保存成功' + redirect_to edit_admins_mirror_repository_mirror_script_path(current_mirror, @script) + else + flash[:danger] = '保存失败' + render 'new' + end + end + + def edit + @script = current_script + end + + def update + @script = current_script + + if @script.update(form_params) + flash[:success] = '保存成功' + redirect_to edit_admins_mirror_repository_mirror_script_path(current_mirror, @script) + else + flash[:danger] = '保存失败' + render 'edit' + end + end + + def destroy + current_script.destroy! + render_delete_success + end + + private + + def current_script + @_current_script ||= current_mirror.mirror_scripts.find(params[:id]) + end + + def current_mirror + @_current_mirror ||= MirrorRepository.find(params[:mirror_repository_id]) + end + + def form_params + params.require(:mirror_script).permit(:script_type, :description, :script) + end +end \ No newline at end of file diff --git a/app/controllers/concerns/admins/render_helper.rb b/app/controllers/concerns/admins/render_helper.rb index 80f008b08..94b7c29cb 100644 --- a/app/controllers/concerns/admins/render_helper.rb +++ b/app/controllers/concerns/admins/render_helper.rb @@ -7,7 +7,7 @@ module Admins::RenderHelper end def render_forbidden - render_by_format(html: -> { redirect_to '/403' }, + render_by_format(html: -> { current_user&.business? ? render('admins/shared/403') : redirect_to('/403') }, json: -> { render status: 403, json: { messages: I18n.t('error.forbidden') } } ) end diff --git a/app/views/admins/mirror_repositories/shared/_list.html.erb b/app/views/admins/mirror_repositories/shared/_list.html.erb index b4c2df70e..fcf0d03a2 100644 --- a/app/views/admins/mirror_repositories/shared/_list.html.erb +++ b/app/views/admins/mirror_repositories/shared/_list.html.erb @@ -24,8 +24,8 @@ <%= mirror.updated_at.strftime('%Y-%m-%d %H:%M') %> <% if mirror.main_type == "1" %> - <%= link_to "/users/modify_script?mirror_id=#{mirror.id}", target: '_blank' do %> - + <%= link_to admins_mirror_repository_mirror_scripts_path(mirror) do %> + <% end %> <% end %> diff --git a/app/views/admins/mirror_scripts/edit.html.erb b/app/views/admins/mirror_scripts/edit.html.erb new file mode 100644 index 000000000..bc3a6ec91 --- /dev/null +++ b/app/views/admins/mirror_scripts/edit.html.erb @@ -0,0 +1,8 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %> + <% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %> + <% add_admin_breadcrumb('脚本列表', admins_mirror_repository_mirror_scripts_path(current_mirror)) %> + <% add_admin_breadcrumb('编辑脚本') %> +<% end %> + +<%= render partial: 'admins/mirror_scripts/shared/form', locals: { mirror: current_mirror, script: @script, form_action: 'update' } %> \ No newline at end of file diff --git a/app/views/admins/mirror_scripts/index.html.erb b/app/views/admins/mirror_scripts/index.html.erb new file mode 100644 index 000000000..f4fa398af --- /dev/null +++ b/app/views/admins/mirror_scripts/index.html.erb @@ -0,0 +1,14 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %> + <% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %> + <% add_admin_breadcrumb('脚本列表') %> +<% end %> + +
+
+ <%= link_to '新建', new_admins_mirror_repository_mirror_script_path(current_mirror), class: 'btn btn-primary' %> +
+ +
+ <%= render partial: 'admins/mirror_scripts/shared/list', locals: { mirror: current_mirror, scripts: @scripts } %> +
diff --git a/app/views/admins/mirror_scripts/new.html.erb b/app/views/admins/mirror_scripts/new.html.erb new file mode 100644 index 000000000..4d6717f41 --- /dev/null +++ b/app/views/admins/mirror_scripts/new.html.erb @@ -0,0 +1,8 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %> + <% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %> + <% add_admin_breadcrumb('脚本列表', admins_mirror_repository_mirror_scripts_path(current_mirror)) %> + <% add_admin_breadcrumb('新建脚本') %> +<% end %> + +<%= render partial: 'admins/mirror_scripts/shared/form', locals: { mirror: current_mirror, script: @script, form_action: 'create' } %> \ No newline at end of file diff --git a/app/views/admins/mirror_scripts/shared/_form.html.erb b/app/views/admins/mirror_scripts/shared/_form.html.erb new file mode 100644 index 000000000..c538e9f73 --- /dev/null +++ b/app/views/admins/mirror_scripts/shared/_form.html.erb @@ -0,0 +1,12 @@ +
+ <%= simple_form_for([:admins, mirror, script], url: { action: form_action }, html: { class: 'script-form' }) do |f| %> + <%= f.input :script_type, label: '名称', input_html: { class: 'col-md-6' } %> + <%= f.input :description, as: :text, label: '说明', input_html: { class: 'col-md-6' } %> + <%= f.input :script, as: :text, label: '评测脚本' %> + +
+ <%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4', 'data-disable-with': '保存中...' %> + <%= link_to '取消', admins_mirror_repository_mirror_scripts_path(mirror), class: 'btn btn-secondary px-4' %> +
+ <% end %> +
\ No newline at end of file diff --git a/app/views/admins/mirror_scripts/shared/_list.html.erb b/app/views/admins/mirror_scripts/shared/_list.html.erb new file mode 100644 index 000000000..30aff38c7 --- /dev/null +++ b/app/views/admins/mirror_scripts/shared/_list.html.erb @@ -0,0 +1,32 @@ + + + + + + + + + + + + <% if scripts.present? %> + <% scripts.each do |script| %> + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
ID名称说明更新时间操作
<%= script.id %><%= overflow_hidden_span script.script_type, width: 200 %><%= overflow_hidden_span script.description, width: 400 %><%= script.updated_at.strftime('%Y-%m-%d %H:%M') %> + <%= link_to '编辑', edit_admins_mirror_repository_mirror_script_path(mirror, script), class: 'action edit-action' %> + + <%= delete_link '删除', admins_mirror_repository_mirror_script_path(mirror, script, element: ".mirror-script-item-#{script.id}"), class: 'delete-mirror-script-action' %> +
+ +<%= render partial: 'admins/shared/paginate', locals: { objects: scripts } %> \ No newline at end of file diff --git a/app/views/admins/shared/403.html.erb b/app/views/admins/shared/403.html.erb new file mode 100644 index 000000000..47e5e9038 --- /dev/null +++ b/app/views/admins/shared/403.html.erb @@ -0,0 +1,6 @@ +
+
+ 403 +
+
未授权
+
\ No newline at end of file diff --git a/config/admins/sidebar.yml b/config/admins/sidebar.yml index d58b92ad9..30af794b7 100644 --- a/config/admins/sidebar.yml +++ b/config/admins/sidebar.yml @@ -1 +1 @@ -admins-users: admins-users \ No newline at end of file +admins-mirror_scripts: 'admins-mirror_repositories' \ No newline at end of file diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 922969938..e6574027e 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -7,8 +7,10 @@ Rails.application.config.assets.version = '1.0' # Rails.application.config.assets.paths << Emoji.images_path # Add Yarn node_modules folder to the asset load path. Rails.application.config.assets.paths << Rails.root.join('node_modules') +Rails.application.config.assets.paths << Rails.root.join('vendor/assets') # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. Rails.application.config.assets.precompile += %w( admin.js admin.css ) + diff --git a/config/routes.rb b/config/routes.rb index 285bb7e1a..ebe9d1a08 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -791,6 +791,8 @@ Rails.application.routes.draw do post :merge get :for_select end + + resources :mirror_scripts, only: [:index, :new, :create, :edit, :update, :destroy] end resources :choose_mirror_repositories, only: [:new, :create] end diff --git a/public/assets/.sprockets-manifest-1c370772f16743f825981ab0e5c94237.json b/public/assets/.sprockets-manifest-1c370772f16743f825981ab0e5c94237.json index da6cf8633..cb63b8f15 100644 --- a/public/assets/.sprockets-manifest-1c370772f16743f825981ab0e5c94237.json +++ b/public/assets/.sprockets-manifest-1c370772f16743f825981ab0e5c94237.json @@ -1 +1 @@ -{"files":{"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js":{"logical_path":"admin.js","mtime":"2019-08-26T15:21:11+08:00","size":907839,"digest":"6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d","integrity":"sha256-ZXXxOZlT+xk1wDenuL0oxK/we3C+2bQfr2iZqJr0tX0="},"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css":{"logical_path":"admin.css","mtime":"2019-08-26T15:21:47+08:00","size":655571,"digest":"8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5","integrity":"sha256-iisDy4oFXcY/RUQ7MEyudzgjMb66VbFXCz08iqQkQtU="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-08-21T15:10:12+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js":{"logical_path":"application.js","mtime":"2019-08-26T15:21:11+08:00","size":1042232,"digest":"a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533","integrity":"sha256-o6TzVJ1oZwVyuwdwDIWprBHlNu3HP+9udIlyO/U15TM="},"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css":{"logical_path":"application.css","mtime":"2019-08-26T15:21:47+08:00","size":1182859,"digest":"a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46","integrity":"sha256-p1CLiOtqaaWzAWAr3cFHRc7AmFPqfZHG+uhWuW54j0Y="},"admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js":{"logical_path":"admin.js","mtime":"2019-08-27T16:36:09+08:00","size":912415,"digest":"7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5","integrity":"sha256-eFnzThB+w1iAwgOmxx+9C2ud/dAHubh0HbPF+vsi16U="},"admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css":{"logical_path":"admin.css","mtime":"2019-08-27T10:22:33+08:00","size":655943,"digest":"e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909","integrity":"sha256-6TUrQDRuLDbB1N6PboBAUQJkdDDawfgeatjvmTVQWQk="},"application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js":{"logical_path":"application.js","mtime":"2019-08-27T16:36:09+08:00","size":1046808,"digest":"a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687","integrity":"sha256-pNbFFV2lod+7cpH68J9VXVV+5C7Z6ywMCU0QiY41xoc="},"application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css":{"logical_path":"application.css","mtime":"2019-08-27T10:22:33+08:00","size":1183231,"digest":"3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17","integrity":"sha256-PQdAVU9xCLuhDXnTTwzEfcoadPoKHEI//9Xe+Zw4bhc="}},"assets":{"admin.js":"admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js","admin.css":"admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js","application.css":"application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css"}} \ No newline at end of file +{"files":{"admin-6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d.js":{"logical_path":"admin.js","mtime":"2019-08-26T15:21:11+08:00","size":907839,"digest":"6575f1399953fb1935c037a7b8bd28c4aff07b70bed9b41faf6899a89af4b57d","integrity":"sha256-ZXXxOZlT+xk1wDenuL0oxK/we3C+2bQfr2iZqJr0tX0="},"admin-8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5.css":{"logical_path":"admin.css","mtime":"2019-08-26T15:21:47+08:00","size":655571,"digest":"8a2b03cb8a055dc63f45443b304cae77382331beba55b1570b3d3c8aa42442d5","integrity":"sha256-iisDy4oFXcY/RUQ7MEyudzgjMb66VbFXCz08iqQkQtU="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-08-22T16:56:33+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533.js":{"logical_path":"application.js","mtime":"2019-08-26T15:21:11+08:00","size":1042232,"digest":"a3a4f3549d68670572bb07700c85a9ac11e536edc73fef6e7489723bf535e533","integrity":"sha256-o6TzVJ1oZwVyuwdwDIWprBHlNu3HP+9udIlyO/U15TM="},"application-a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46.css":{"logical_path":"application.css","mtime":"2019-08-26T15:21:47+08:00","size":1182859,"digest":"a7508b88eb6a69a5b301602bddc14745cec09853ea7d91c6fae856b96e788f46","integrity":"sha256-p1CLiOtqaaWzAWAr3cFHRc7AmFPqfZHG+uhWuW54j0Y="},"admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js":{"logical_path":"admin.js","mtime":"2019-08-27T16:36:09+08:00","size":912415,"digest":"7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5","integrity":"sha256-eFnzThB+w1iAwgOmxx+9C2ud/dAHubh0HbPF+vsi16U="},"admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css":{"logical_path":"admin.css","mtime":"2019-08-27T10:22:33+08:00","size":655943,"digest":"e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909","integrity":"sha256-6TUrQDRuLDbB1N6PboBAUQJkdDDawfgeatjvmTVQWQk="},"application-a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687.js":{"logical_path":"application.js","mtime":"2019-08-27T16:36:09+08:00","size":1046808,"digest":"a4d6c5155da5a1dfbb7291faf09f555d557ee42ed9eb2c0c094d10898e35c687","integrity":"sha256-pNbFFV2lod+7cpH68J9VXVV+5C7Z6ywMCU0QiY41xoc="},"application-3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17.css":{"logical_path":"application.css","mtime":"2019-08-27T10:22:33+08:00","size":1183231,"digest":"3d0740554f7108bba10d79d34f0cc47dca1a74fa0a1c423fffd5def99c386e17","integrity":"sha256-PQdAVU9xCLuhDXnTTwzEfcoadPoKHEI//9Xe+Zw4bhc="},"admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js":{"logical_path":"admin.js","mtime":"2019-08-28T10:13:52+08:00","size":1314165,"digest":"d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773","integrity":"sha256-2Xbg/j/78d4Xo0Bx42zpK4lx61t4vYhdsNyZxzxNN3M="},"admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css":{"logical_path":"admin.css","mtime":"2019-08-28T09:55:16+08:00","size":670071,"digest":"c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b","integrity":"sha256-xCVvq3HdhOb2CRtaiG+j5za7zr7VG1A+qZciIQIq22s="},"application-a044d1142b1e21bfda21aab2e22e08889343ad253b5847d446cee9620b2f51f0.js":{"logical_path":"application.js","mtime":"2019-08-28T10:13:52+08:00","size":1448558,"digest":"a044d1142b1e21bfda21aab2e22e08889343ad253b5847d446cee9620b2f51f0","integrity":"sha256-oETRFCseIb/aIaqy4i4IiJNDrSU7WEfURs7pYgsvUfA="},"application-378235e0207ed9f59fd6201c7b0971fae73f23e39cee0ed1464e007bd016a376.css":{"logical_path":"application.css","mtime":"2019-08-28T09:55:16+08:00","size":1197485,"digest":"378235e0207ed9f59fd6201c7b0971fae73f23e39cee0ed1464e007bd016a376","integrity":"sha256-N4I14CB+2fWf1iAcewlx+uc/I+Oc7g7RRk4Ae9AWo3Y="}},"assets":{"admin.js":"admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js","admin.css":"admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-a044d1142b1e21bfda21aab2e22e08889343ad253b5847d446cee9620b2f51f0.js","application.css":"application-378235e0207ed9f59fd6201c7b0971fae73f23e39cee0ed1464e007bd016a376.css"}} \ No newline at end of file diff --git a/public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css b/public/assets/admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css similarity index 97% rename from public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css rename to public/assets/admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css index 25449185a..3765830c4 100644 --- a/public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css +++ b/public/assets/admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css @@ -17816,6 +17816,607 @@ form.was-validated select:valid ~ .select2-container--bootstrap4 .select2-select .datepicker.datepicker-inline td { padding: 4px 5px; } +/* BASICS */ +/* line 3, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; + color: black; + direction: ltr; +} + +/* PADDING */ +/* line 13, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-lines { + padding: 4px 0; + /* Vertical padding around content */ +} + +/* line 16, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror pre.CodeMirror-line, +.CodeMirror pre.CodeMirror-line-like { + padding: 0 4px; + /* Horizontal padding of content */ +} + +/* line 21, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + background-color: white; + /* The little square between H and V scrollbars */ +} + +/* GUTTER */ +/* line 27, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; + white-space: nowrap; +} + +/* line 33, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; + white-space: nowrap; +} + +/* line 41, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-guttermarker { + color: black; +} + +/* line 42, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-guttermarker-subtle { + color: #999; +} + +/* CURSOR */ +/* line 46, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-cursor { + border-left: 1px solid black; + border-right: none; + width: 0; +} + +/* Shown when moving in bi-directional text */ +/* line 52, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} + +/* line 55, vendor/assets/codemirror/lib/codemirror.css */ +.cm-fat-cursor .CodeMirror-cursor { + width: auto; + border: 0 !important; + background: #7e7; +} + +/* line 60, vendor/assets/codemirror/lib/codemirror.css */ +.cm-fat-cursor div.CodeMirror-cursors { + z-index: 1; +} + +/* line 63, vendor/assets/codemirror/lib/codemirror.css */ +.cm-fat-cursor-mark { + background-color: rgba(20, 255, 20, 0.5); + -webkit-animation: blink 1.06s steps(1) infinite; + animation: blink 1.06s steps(1) infinite; +} + +/* line 69, vendor/assets/codemirror/lib/codemirror.css */ +.cm-animate-fat-cursor { + width: auto; + border: 0; + -webkit-animation: blink 1.06s steps(1) infinite; + animation: blink 1.06s steps(1) infinite; + background-color: #7e7; +} + +@-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 */ +/* line 96, vendor/assets/codemirror/lib/codemirror.css */ +.cm-tab { + display: inline-block; + text-decoration: inherit; +} + +/* line 98, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-rulers { + position: absolute; + left: 0; + right: 0; + top: -50px; + bottom: 0; + overflow: hidden; +} + +/* line 103, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-ruler { + border-left: 1px solid #ccc; + top: 0; + bottom: 0; + position: absolute; +} + +/* DEFAULT THEME */ +/* line 111, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-header { + color: blue; +} + +/* line 112, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-quote { + color: #090; +} + +/* line 113, vendor/assets/codemirror/lib/codemirror.css */ +.cm-negative { + color: #d44; +} + +/* line 114, vendor/assets/codemirror/lib/codemirror.css */ +.cm-positive { + color: #292; +} + +/* line 115, vendor/assets/codemirror/lib/codemirror.css */ +.cm-header, .cm-strong { + font-weight: bold; +} + +/* line 116, vendor/assets/codemirror/lib/codemirror.css */ +.cm-em { + font-style: italic; +} + +/* line 117, vendor/assets/codemirror/lib/codemirror.css */ +.cm-link { + text-decoration: underline; +} + +/* line 118, vendor/assets/codemirror/lib/codemirror.css */ +.cm-strikethrough { + text-decoration: line-through; +} + +/* line 120, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-keyword { + color: #708; +} + +/* line 121, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-atom { + color: #219; +} + +/* line 122, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-number { + color: #164; +} + +/* line 123, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-def { + color: #00f; +} + +/* line 128, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-variable-2 { + color: #05a; +} + +/* line 129, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-variable-3, .cm-s-default .cm-type { + color: #085; +} + +/* line 130, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-comment { + color: #a50; +} + +/* line 131, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-string { + color: #a11; +} + +/* line 132, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-string-2 { + color: #f50; +} + +/* line 133, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-meta { + color: #555; +} + +/* line 134, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-qualifier { + color: #555; +} + +/* line 135, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-builtin { + color: #30a; +} + +/* line 136, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-bracket { + color: #997; +} + +/* line 137, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-tag { + color: #170; +} + +/* line 138, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-attribute { + color: #00c; +} + +/* line 139, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-hr { + color: #999; +} + +/* line 140, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-link { + color: #00c; +} + +/* line 142, vendor/assets/codemirror/lib/codemirror.css */ +.cm-s-default .cm-error { + color: #f00; +} + +/* line 143, vendor/assets/codemirror/lib/codemirror.css */ +.cm-invalidchar { + color: #f00; +} + +/* line 145, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-composing { + border-bottom: 2px solid; +} + +/* Default styles for common addons */ +/* line 149, vendor/assets/codemirror/lib/codemirror.css */ +div.CodeMirror span.CodeMirror-matchingbracket { + color: #0b0; +} + +/* line 150, vendor/assets/codemirror/lib/codemirror.css */ +div.CodeMirror span.CodeMirror-nonmatchingbracket { + color: #a22; +} + +/* line 151, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-matchingtag { + background: rgba(255, 150, 0, 0.3); +} + +/* line 152, vendor/assets/codemirror/lib/codemirror.css */ +.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. */ +/* line 159, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror { + position: relative; + overflow: hidden; + background: white; +} + +/* line 165, vendor/assets/codemirror/lib/codemirror.css */ +.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; +} + +/* line 175, vendor/assets/codemirror/lib/codemirror.css */ +.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. */ +/* line 183, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + position: absolute; + z-index: 6; + display: none; +} + +/* line 188, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-vscrollbar { + right: 0; + top: 0; + overflow-x: hidden; + overflow-y: scroll; +} + +/* line 193, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-hscrollbar { + bottom: 0; + left: 0; + overflow-y: hidden; + overflow-x: scroll; +} + +/* line 198, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-scrollbar-filler { + right: 0; + bottom: 0; +} + +/* line 201, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutter-filler { + left: 0; + bottom: 0; +} + +/* line 205, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutters { + position: absolute; + left: 0; + top: 0; + min-height: 100%; + z-index: 3; +} + +/* line 210, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutter { + white-space: normal; + height: 100%; + display: inline-block; + vertical-align: top; + margin-bottom: -30px; +} + +/* line 217, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutter-wrapper { + position: absolute; + z-index: 4; + background: none !important; + border: none !important; +} + +/* line 223, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutter-background { + position: absolute; + top: 0; + bottom: 0; + z-index: 4; +} + +/* line 228, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} + +/* line 233, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutter-wrapper ::-moz-selection { + background-color: transparent; +} +.CodeMirror-gutter-wrapper ::selection { + background-color: transparent; +} + +/* line 234, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-gutter-wrapper ::-moz-selection { + background-color: transparent; +} + +/* line 236, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-lines { + cursor: text; + min-height: 1px; + /* prevents collapsing before first draw */ +} + +/* line 240, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror pre.CodeMirror-line, +.CodeMirror pre.CodeMirror-line-like { + /* Reset some styles that the rest of the page might have set */ + 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: contextual; + font-variant-ligatures: contextual; +} + +/* line 260, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-wrap pre.CodeMirror-line, +.CodeMirror-wrap pre.CodeMirror-line-like { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} + +/* line 267, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-linebackground { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 0; +} + +/* line 273, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-linewidget { + position: relative; + z-index: 2; + padding: 0.1px; + /* Force widget margins to stay inside of the container */ +} + +/* line 281, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-rtl pre { + direction: rtl; +} + +/* line 283, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-code { + outline: none; +} + +/* Force content-box sizing for the elements where we expect it */ +/* line 288, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-scroll, +.CodeMirror-sizer, +.CodeMirror-gutter, +.CodeMirror-gutters, +.CodeMirror-linenumber { + box-sizing: content-box; +} + +/* line 297, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-measure { + position: absolute; + width: 100%; + height: 0; + overflow: hidden; + visibility: hidden; +} + +/* line 305, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-cursor { + position: absolute; + pointer-events: none; +} + +/* line 309, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-measure pre { + position: static; +} + +/* line 311, vendor/assets/codemirror/lib/codemirror.css */ +div.CodeMirror-cursors { + visibility: hidden; + position: relative; + z-index: 3; +} + +/* line 316, vendor/assets/codemirror/lib/codemirror.css */ +div.CodeMirror-dragcursors { + visibility: visible; +} + +/* line 320, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-focused div.CodeMirror-cursors { + visibility: visible; +} + +/* line 324, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-selected { + background: #d9d9d9; +} + +/* line 325, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-focused .CodeMirror-selected { + background: #d7d4f0; +} + +/* line 326, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-crosshair { + cursor: crosshair; +} + +/* line 327, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { + background: #d7d4f0; +} +.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { + background: #d7d4f0; +} + +/* line 328, vendor/assets/codemirror/lib/codemirror.css */ +.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { + background: #d7d4f0; +} + +/* line 330, vendor/assets/codemirror/lib/codemirror.css */ +.cm-searching { + background-color: #ffa; + background-color: rgba(255, 255, 0, 0.4); +} + +/* Used to force a border model for a node */ +/* line 336, vendor/assets/codemirror/lib/codemirror.css */ +.cm-force-border { + padding-right: .1px; +} + +@media print { + /* Hide the cursor when printing */ + /* line 340, vendor/assets/codemirror/lib/codemirror.css */ + .CodeMirror div.CodeMirror-cursors { + visibility: hidden; + } +} + +/* See issue #2901 */ +/* line 346, vendor/assets/codemirror/lib/codemirror.css */ +.cm-tab-wrap-hack:after { + content: ''; +} + +/* Help users use markselection to safely style text background */ +/* line 349, vendor/assets/codemirror/lib/codemirror.css */ +span.CodeMirror-selectedtext { + background: none; +} + /* line 1, app/assets/stylesheets/admins/common.scss */ .admin-body-container { padding: 20px; @@ -17952,6 +18553,11 @@ form.was-validated select:valid ~ .select2-container--bootstrap4 .select2-select padding: 0.5rem 2rem; } +/* line 110, app/assets/stylesheets/admins/common.scss */ +.admin-body-container .CodeMirror { + border: 1px solid #ced4da; +} + /* line 2, app/assets/stylesheets/admins/daily_school_statistics.scss */ .admins-daily-school-statistics-index-page .daily-school-statistic-list-container { text-align: center; @@ -18359,7 +18965,7 @@ form.was-validated select:valid ~ .select2-container--bootstrap4 .select2-select text-align: center; } -/* line 11, app/assets/stylesheets/admin.scss */ +/* line 12, app/assets/stylesheets/admin.scss */ body { width: 100vw; height: 100vh; @@ -18373,53 +18979,53 @@ body { background: #efefef; } -/* line 23, app/assets/stylesheets/admin.scss */ +/* line 24, app/assets/stylesheets/admin.scss */ a:hover { text-decoration: unset; } -/* line 28, app/assets/stylesheets/admin.scss */ +/* line 29, app/assets/stylesheets/admin.scss */ textarea.danger, input.danger { border-color: #dc3545 !important; } -/* line 32, app/assets/stylesheets/admin.scss */ +/* line 33, app/assets/stylesheets/admin.scss */ label.error { color: #dc3545 !important; } -/* line 38, app/assets/stylesheets/admin.scss */ +/* line 39, app/assets/stylesheets/admin.scss */ .simple_form .form-group .collection_radio_buttons { margin-bottom: 0px; } -/* line 42, app/assets/stylesheets/admin.scss */ +/* line 43, app/assets/stylesheets/admin.scss */ .simple_form .form-group .form-check-inline { height: calc(1.5em + 0.75rem + 2px); } -/* line 48, app/assets/stylesheets/admin.scss */ +/* line 49, app/assets/stylesheets/admin.scss */ .flex-1 { -webkit-box-flex: 1; flex: 1; } -/* line 52, app/assets/stylesheets/admin.scss */ +/* line 53, app/assets/stylesheets/admin.scss */ .font-12 { font-size: 12px !important; } -/* line 53, app/assets/stylesheets/admin.scss */ +/* line 54, app/assets/stylesheets/admin.scss */ .font-14 { font-size: 14px !important; } -/* line 54, app/assets/stylesheets/admin.scss */ +/* line 55, app/assets/stylesheets/admin.scss */ .font-16 { font-size: 16px !important; } -/* line 55, app/assets/stylesheets/admin.scss */ +/* line 56, app/assets/stylesheets/admin.scss */ .font-18 { font-size: 18px !important; } diff --git a/public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css.gz b/public/assets/admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css.gz similarity index 57% rename from public/assets/admin-e9352b40346e2c36c1d4de8f6e80405102647430dac1f81e6ad8ef9935505909.css.gz rename to public/assets/admin-c4256fab71dd84e6f6091b5a886fa3e736bbcebed51b503ea9972221022adb6b.css.gz index d54280d98eb49ac709545c59928ffb306ed0ac43..ae00dc58dbe76befbe6a8e69cfad6c586682ac45 100644 GIT binary patch delta 22467 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 Sd-x#t@c#oFH~!jpISK%PKmZH? delta 19925 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 diff --git a/public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js b/public/assets/admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js similarity index 69% rename from public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js rename to public/assets/admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js index e96beedb5..16be1af45 100644 --- a/public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js +++ b/public/assets/admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js @@ -27613,6 +27613,9923 @@ $.fn.bootstrapViewer.defaults = { src: 'src' } ; +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/LICENSE + +// This is CodeMirror (https://codemirror.net), a code editor +// implemented in JavaScript on top of the browser's DOM. +// +// You can find some technical background for some of the code below +// at http://marijnhaverbeke.nl/blog/#cm-internals . + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.CodeMirror = factory()); +}(this, (function () { 'use strict'; + + // Kludges for bugs and behavior differences that can't be feature + // detected are enabled based on userAgent etc sniffing. + var userAgent = navigator.userAgent; + var platform = navigator.platform; + + var gecko = /gecko\/\d/i.test(userAgent); + var ie_upto10 = /MSIE \d/.test(userAgent); + var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); + var edge = /Edge\/(\d+)/.exec(userAgent); + var ie = ie_upto10 || ie_11up || edge; + var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]); + var webkit = !edge && /WebKit\//.test(userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); + var chrome = !edge && /Chrome\//.test(userAgent); + var presto = /Opera\//.test(userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); + var phantom = /PhantomJS/.test(userAgent); + + var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); + var android = /Android/.test(userAgent); + // This is woefully incomplete. Suggestions for alternative methods welcome. + var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); + var mac = ios || /Mac/.test(platform); + var chromeOS = /\bCrOS\b/.test(userAgent); + var windows = /win/i.test(platform); + + var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); + if (presto_version) { presto_version = Number(presto_version[1]); } + if (presto_version && presto_version >= 15) { presto = false; webkit = true; } + // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); + var captureRightClick = gecko || (ie && ie_version >= 9); + + function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } + + var rmClass = function(node, cls) { + var current = node.className; + var match = classTest(cls).exec(current); + if (match) { + var after = current.slice(match.index + match[0].length); + node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); + } + }; + + function removeChildren(e) { + for (var count = e.childNodes.length; count > 0; --count) + { e.removeChild(e.firstChild); } + return e + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e) + } + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + if (className) { e.className = className; } + if (style) { e.style.cssText = style; } + if (typeof content == "string") { e.appendChild(document.createTextNode(content)); } + else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } } + return e + } + // wrapper for elt, which removes the elt from the accessibility tree + function eltP(tag, content, className, style) { + var e = elt(tag, content, className, style); + e.setAttribute("role", "presentation"); + return e + } + + var range; + if (document.createRange) { range = function(node, start, end, endNode) { + var r = document.createRange(); + r.setEnd(endNode || node, end); + r.setStart(node, start); + return r + }; } + else { range = function(node, start, end) { + var r = document.body.createTextRange(); + try { r.moveToElementText(node.parentNode); } + catch(e) { return r } + r.collapse(true); + r.moveEnd("character", end); + r.moveStart("character", start); + return r + }; } + + function contains(parent, child) { + if (child.nodeType == 3) // Android browser always returns false when child is a textnode + { child = child.parentNode; } + if (parent.contains) + { return parent.contains(child) } + do { + if (child.nodeType == 11) { child = child.host; } + if (child == parent) { return true } + } while (child = child.parentNode) + } + + function activeElt() { + // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. + // IE < 10 will throw when accessed while the page is loading or in an iframe. + // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. + var activeElement; + try { + activeElement = document.activeElement; + } catch(e) { + activeElement = document.body || null; + } + while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) + { activeElement = activeElement.shadowRoot.activeElement; } + return activeElement + } + + function addClass(node, cls) { + var current = node.className; + if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; } + } + function joinClasses(a, b) { + var as = a.split(" "); + for (var i = 0; i < as.length; i++) + { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } } + return b + } + + var selectInput = function(node) { node.select(); }; + if (ios) // Mobile Safari apparently has a bug where select() is broken. + { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; } + else if (ie) // Suppress mysterious IE10 errors + { selectInput = function(node) { try { node.select(); } catch(_e) {} }; } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function(){return f.apply(null, args)} + } + + function copyObj(obj, target, overwrite) { + if (!target) { target = {}; } + for (var prop in obj) + { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) + { target[prop] = obj[prop]; } } + return target + } + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countColumn(string, end, tabSize, startIndex, startValue) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) { end = string.length; } + } + for (var i = startIndex || 0, n = startValue || 0;;) { + var nextTab = string.indexOf("\t", i); + if (nextTab < 0 || nextTab >= end) + { return n + (end - i) } + n += nextTab - i; + n += tabSize - (n % tabSize); + i = nextTab + 1; + } + } + + var Delayed = function() {this.id = null;}; + Delayed.prototype.set = function (ms, f) { + clearTimeout(this.id); + this.id = setTimeout(f, ms); + }; + + function indexOf(array, elt) { + for (var i = 0; i < array.length; ++i) + { if (array[i] == elt) { return i } } + return -1 + } + + // Number of pixels added to scroller and sizer to hide scrollbar + var scrollerGap = 30; + + // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + var Pass = {toString: function(){return "CodeMirror.Pass"}}; + + // Reused option objects for setSelection & friends + var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; + + // The inverse of countColumn -- find the offset that corresponds to + // a particular column. + function findColumn(string, goal, tabSize) { + for (var pos = 0, col = 0;;) { + var nextTab = string.indexOf("\t", pos); + if (nextTab == -1) { nextTab = string.length; } + var skipped = nextTab - pos; + if (nextTab == string.length || col + skipped >= goal) + { return pos + Math.min(skipped, goal - col) } + col += nextTab - pos; + col += tabSize - (col % tabSize); + pos = nextTab + 1; + if (col >= goal) { return pos } + } + } + + var spaceStrs = [""]; + function spaceStr(n) { + while (spaceStrs.length <= n) + { spaceStrs.push(lst(spaceStrs) + " "); } + return spaceStrs[n] + } + + function lst(arr) { return arr[arr.length-1] } + + function map(array, f) { + var out = []; + for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); } + return out + } + + function insertSorted(array, value, score) { + var pos = 0, priority = score(value); + while (pos < array.length && score(array[pos]) <= priority) { pos++; } + array.splice(pos, 0, value); + } + + function nothing() {} + + function createObj(base, props) { + var inst; + if (Object.create) { + inst = Object.create(base); + } else { + nothing.prototype = base; + inst = new nothing(); + } + if (props) { copyObj(props, inst); } + return inst + } + + var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + function isWordCharBasic(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) + } + function isWordChar(ch, helper) { + if (!helper) { return isWordCharBasic(ch) } + if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } + return helper.test(ch) + } + + function isEmpty(obj) { + for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } + return true + } + + // Extending unicode characters. A series of a non-extending char + + // any number of extending chars is treated as a single unit as far + // as editing and measuring is concerned. This is not fully correct, + // since some scripts/fonts/browsers also treat other configurations + // of code points as a group. + var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } + + // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. + function skipExtendingChars(str, pos, dir) { + while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; } + return pos + } + + // Returns the value from the range [`from`; `to`] that satisfies + // `pred` and is closest to `from`. Assumes that at least `to` + // satisfies `pred`. Supports `from` being greater than `to`. + function findFirst(pred, from, to) { + // At any point we are certain `to` satisfies `pred`, don't know + // whether `from` does. + var dir = from > to ? -1 : 1; + for (;;) { + if (from == to) { return from } + var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF); + if (mid == from) { return pred(mid) ? from : to } + if (pred(mid)) { to = mid; } + else { from = mid + dir; } + } + } + + // BIDI HELPERS + + function iterateBidiSections(order, from, to, f) { + if (!order) { return f(from, to, "ltr", 0) } + var found = false; + for (var i = 0; i < order.length; ++i) { + var part = order[i]; + if (part.from < to && part.to > from || from == to && part.to == from) { + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i); + found = true; + } + } + if (!found) { f(from, to, "ltr"); } + } + + var bidiOther = null; + function getBidiPartAt(order, ch, sticky) { + var found; + bidiOther = null; + for (var i = 0; i < order.length; ++i) { + var cur = order[i]; + if (cur.from < ch && cur.to > ch) { return i } + if (cur.to == ch) { + if (cur.from != cur.to && sticky == "before") { found = i; } + else { bidiOther = i; } + } + if (cur.from == ch) { + if (cur.from != cur.to && sticky != "before") { found = i; } + else { bidiOther = i; } + } + } + return found != null ? found : bidiOther + } + + // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + var bidiOrdering = (function() { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; + // Character types for codepoints 0x600 to 0x6f9 + var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"; + function charType(code) { + if (code <= 0xf7) { return lowTypes.charAt(code) } + else if (0x590 <= code && code <= 0x5f4) { return "R" } + else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } + else if (0x6ee <= code && code <= 0x8ac) { return "r" } + else if (0x2000 <= code && code <= 0x200b) { return "w" } + else if (code == 0x200c) { return "b" } + else { return "L" } + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; + + function BidiSpan(level, from, to) { + this.level = level; + this.from = from; this.to = to; + } + + return function(str, direction) { + var outerType = direction == "ltr" ? "L" : "R"; + + if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false } + var len = str.length, types = []; + for (var i = 0; i < len; ++i) + { types.push(charType(str.charCodeAt(i))); } + + // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { + var type = types[i$1]; + if (type == "m") { types[i$1] = prev; } + else { prev = type; } + } + + // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { + var type$1 = types[i$2]; + if (type$1 == "1" && cur == "r") { types[i$2] = "n"; } + else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } } + } + + // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { + var type$2 = types[i$3]; + if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; } + else if (type$2 == "," && prev$1 == types[i$3+1] && + (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; } + prev$1 = type$2; + } + + // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + for (var i$4 = 0; i$4 < len; ++i$4) { + var type$3 = types[i$4]; + if (type$3 == ",") { types[i$4] = "N"; } + else if (type$3 == "%") { + var end = (void 0); + for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} + var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; + for (var j = i$4; j < end; ++j) { types[j] = replace; } + i$4 = end - 1; + } + } + + // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { + var type$4 = types[i$5]; + if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; } + else if (isStrong.test(type$4)) { cur$1 = type$4; } + } + + // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + for (var i$6 = 0; i$6 < len; ++i$6) { + if (isNeutral.test(types[i$6])) { + var end$1 = (void 0); + for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} + var before = (i$6 ? types[i$6-1] : outerType) == "L"; + var after = (end$1 < len ? types[end$1] : outerType) == "L"; + var replace$1 = before == after ? (before ? "L" : "R") : outerType; + for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; } + i$6 = end$1 - 1; + } + } + + // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + var order = [], m; + for (var i$7 = 0; i$7 < len;) { + if (countsAsLeft.test(types[i$7])) { + var start = i$7; + for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} + order.push(new BidiSpan(0, start, i$7)); + } else { + var pos = i$7, at = order.length; + for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} + for (var j$2 = pos; j$2 < i$7;) { + if (countsAsNum.test(types[j$2])) { + if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); } + var nstart = j$2; + for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} + order.splice(at, 0, new BidiSpan(2, nstart, j$2)); + pos = j$2; + } else { ++j$2; } + } + if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); } + } + } + if (direction == "ltr") { + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length; + order.unshift(new BidiSpan(0, 0, m[0].length)); + } + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length; + order.push(new BidiSpan(0, len - m[0].length, len)); + } + } + + return direction == "rtl" ? order.reverse() : order + } + })(); + + // Get the bidi ordering for the given line (and cache it). Returns + // false for lines that are fully left-to-right, and an array of + // BidiSpan objects otherwise. + function getOrder(line, direction) { + var order = line.order; + if (order == null) { order = line.order = bidiOrdering(line.text, direction); } + return order + } + + // EVENT HANDLING + + // Lightweight event framework. on/off also work on DOM nodes, + // registering native DOM handlers. + + var noHandlers = []; + + var on = function(emitter, type, f) { + if (emitter.addEventListener) { + emitter.addEventListener(type, f, false); + } else if (emitter.attachEvent) { + emitter.attachEvent("on" + type, f); + } else { + var map$$1 = emitter._handlers || (emitter._handlers = {}); + map$$1[type] = (map$$1[type] || noHandlers).concat(f); + } + }; + + function getHandlers(emitter, type) { + return emitter._handlers && emitter._handlers[type] || noHandlers + } + + function off(emitter, type, f) { + if (emitter.removeEventListener) { + emitter.removeEventListener(type, f, false); + } else if (emitter.detachEvent) { + emitter.detachEvent("on" + type, f); + } else { + var map$$1 = emitter._handlers, arr = map$$1 && map$$1[type]; + if (arr) { + var index = indexOf(arr, f); + if (index > -1) + { map$$1[type] = arr.slice(0, index).concat(arr.slice(index + 1)); } + } + } + } + + function signal(emitter, type /*, values...*/) { + var handlers = getHandlers(emitter, type); + if (!handlers.length) { return } + var args = Array.prototype.slice.call(arguments, 2); + for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); } + } + + // The DOM events that CodeMirror handles can be overridden by + // registering a (non-DOM) handler on the editor for the event name, + // and preventDefault-ing the event in that handler. + function signalDOMEvent(cm, e, override) { + if (typeof e == "string") + { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; } + signal(cm, override || e.type, cm, e); + return e_defaultPrevented(e) || e.codemirrorIgnore + } + + function signalCursorActivity(cm) { + var arr = cm._handlers && cm._handlers.cursorActivity; + if (!arr) { return } + var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); + for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) + { set.push(arr[i]); } } + } + + function hasHandler(emitter, type) { + return getHandlers(emitter, type).length > 0 + } + + // Add on and off methods to a constructor's prototype, to make + // registering events on such objects more convenient. + function eventMixin(ctor) { + ctor.prototype.on = function(type, f) {on(this, type, f);}; + ctor.prototype.off = function(type, f) {off(this, type, f);}; + } + + // Due to the fact that we still support jurassic IE versions, some + // compatibility wrappers are needed. + + function e_preventDefault(e) { + if (e.preventDefault) { e.preventDefault(); } + else { e.returnValue = false; } + } + function e_stopPropagation(e) { + if (e.stopPropagation) { e.stopPropagation(); } + else { e.cancelBubble = true; } + } + function e_defaultPrevented(e) { + return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false + } + function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} + + function e_target(e) {return e.target || e.srcElement} + function e_button(e) { + var b = e.which; + if (b == null) { + if (e.button & 1) { b = 1; } + else if (e.button & 2) { b = 3; } + else if (e.button & 4) { b = 2; } + } + if (mac && e.ctrlKey && b == 1) { b = 3; } + return b + } + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie && ie_version < 9) { return false } + var div = elt('div'); + return "draggable" in div || "dragDrop" in div + }(); + + var zwspSupported; + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200b"); + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); + if (measure.firstChild.offsetHeight != 0) + { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); } + } + var node = zwspSupported ? elt("span", "\u200b") : + elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); + node.setAttribute("cm-text", ""); + return node + } + + // Feature-detect IE's crummy client rect reporting for bidi text + var badBidiRects; + function hasBadBidiRects(measure) { + if (badBidiRects != null) { return badBidiRects } + var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); + var r0 = range(txt, 0, 1).getBoundingClientRect(); + var r1 = range(txt, 1, 2).getBoundingClientRect(); + removeChildren(measure); + if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) + return badBidiRects = (r1.right - r0.right < 3) + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { + var pos = 0, result = [], l = string.length; + while (pos <= l) { + var nl = string.indexOf("\n", pos); + if (nl == -1) { nl = string.length; } + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + return result + } : function (string) { return string.split(/\r\n?|\n/); }; + + var hasSelection = window.getSelection ? function (te) { + try { return te.selectionStart != te.selectionEnd } + catch(e) { return false } + } : function (te) { + var range$$1; + try {range$$1 = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range$$1 || range$$1.parentElement() != te) { return false } + return range$$1.compareEndPoints("StartToEnd", range$$1) != 0 + }; + + var hasCopyEvent = (function () { + var e = elt("div"); + if ("oncopy" in e) { return true } + e.setAttribute("oncopy", "return;"); + return typeof e.oncopy == "function" + })(); + + var badZoomedRects = null; + function hasBadZoomedRects(measure) { + if (badZoomedRects != null) { return badZoomedRects } + var node = removeChildrenAndAdd(measure, elt("span", "x")); + var normal = node.getBoundingClientRect(); + var fromRange = range(node, 0, 1).getBoundingClientRect(); + return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 + } + + // Known modes, by name and by MIME + var modes = {}, mimeModes = {}; + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + function defineMode(name, mode) { + if (arguments.length > 2) + { mode.dependencies = Array.prototype.slice.call(arguments, 2); } + modes[name] = mode; + } + + function defineMIME(mime, spec) { + mimeModes[mime] = spec; + } + + // Given a MIME type, a {name, ...options} config object, or a name + // string, return a mode config object. + function resolveMode(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { + spec = mimeModes[spec]; + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + var found = mimeModes[spec.name]; + if (typeof found == "string") { found = {name: found}; } + spec = createObj(found, spec); + spec.name = found.name; + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { + return resolveMode("application/xml") + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { + return resolveMode("application/json") + } + if (typeof spec == "string") { return {name: spec} } + else { return spec || {name: "null"} } + } + + // Given a mode spec (anything that resolveMode accepts), find and + // initialize an actual mode object. + function getMode(options, spec) { + spec = resolveMode(spec); + var mfactory = modes[spec.name]; + if (!mfactory) { return getMode(options, "text/plain") } + var modeObj = mfactory(options, spec); + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) { continue } + if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; } + modeObj[prop] = exts[prop]; + } + } + modeObj.name = spec.name; + if (spec.helperType) { modeObj.helperType = spec.helperType; } + if (spec.modeProps) { for (var prop$1 in spec.modeProps) + { modeObj[prop$1] = spec.modeProps[prop$1]; } } + + return modeObj + } + + // This can be used to attach properties to mode objects from + // outside the actual mode definition. + var modeExtensions = {}; + function extendMode(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); + copyObj(properties, exts); + } + + function copyState(mode, state) { + if (state === true) { return state } + if (mode.copyState) { return mode.copyState(state) } + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) { val = val.concat([]); } + nstate[n] = val; + } + return nstate + } + + // Given a mode and a state (for that mode), find the inner mode and + // state at the position that the state refers to. + function innerMode(mode, state) { + var info; + while (mode.innerMode) { + info = mode.innerMode(state); + if (!info || info.mode == mode) { break } + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state} + } + + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true + } + + // STRING STREAM + + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + var StringStream = function(string, tabSize, lineOracle) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + this.lineOracle = lineOracle; + }; + + StringStream.prototype.eol = function () {return this.pos >= this.string.length}; + StringStream.prototype.sol = function () {return this.pos == this.lineStart}; + StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined}; + StringStream.prototype.next = function () { + if (this.pos < this.string.length) + { return this.string.charAt(this.pos++) } + }; + StringStream.prototype.eat = function (match) { + var ch = this.string.charAt(this.pos); + var ok; + if (typeof match == "string") { ok = ch == match; } + else { ok = ch && (match.test ? match.test(ch) : match(ch)); } + if (ok) {++this.pos; return ch} + }; + StringStream.prototype.eatWhile = function (match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start + }; + StringStream.prototype.eatSpace = function () { + var this$1 = this; + + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos; } + return this.pos > start + }; + StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;}; + StringStream.prototype.skipTo = function (ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true} + }; + StringStream.prototype.backUp = function (n) {this.pos -= n;}; + StringStream.prototype.column = function () { + if (this.lastColumnPos < this.start) { + this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); + this.lastColumnPos = this.start; + } + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) + }; + StringStream.prototype.indentation = function () { + return countColumn(this.string, null, this.tabSize) - + (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) + }; + StringStream.prototype.match = function (pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }; + var substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) { this.pos += pattern.length; } + return true + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) { return null } + if (match && consume !== false) { this.pos += match[0].length; } + return match + } + }; + StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)}; + StringStream.prototype.hideFirstChars = function (n, inner) { + this.lineStart += n; + try { return inner() } + finally { this.lineStart -= n; } + }; + StringStream.prototype.lookAhead = function (n) { + var oracle = this.lineOracle; + return oracle && oracle.lookAhead(n) + }; + StringStream.prototype.baseToken = function () { + var oracle = this.lineOracle; + return oracle && oracle.baseToken(this.pos) + }; + + // Find the line object corresponding to the given line number. + function getLine(doc, n) { + n -= doc.first; + if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } + var chunk = doc; + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break } + n -= sz; + } + } + return chunk.lines[n] + } + + // Get the part of a document between two positions, as an array of + // strings. + function getBetween(doc, start, end) { + var out = [], n = start.line; + doc.iter(start.line, end.line + 1, function (line) { + var text = line.text; + if (n == end.line) { text = text.slice(0, end.ch); } + if (n == start.line) { text = text.slice(start.ch); } + out.push(text); + ++n; + }); + return out + } + // Get the lines between from and to, as array of strings. + function getLines(doc, from, to) { + var out = []; + doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value + return out + } + + // Update the height of a line, propagating the height change + // upwards to parent nodes. + function updateLineHeight(line, height) { + var diff = height - line.height; + if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } } + } + + // Given a line object, find its line number by walking up through + // its parent links. + function lineNo(line) { + if (line.parent == null) { return null } + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) { break } + no += chunk.children[i].chunkSize(); + } + } + return no + cur.first + } + + // Find the line at the given vertical position, using the height + // information in the document tree. + function lineAtHeight(chunk, h) { + var n = chunk.first; + outer: do { + for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { + var child = chunk.children[i$1], ch = child.height; + if (h < ch) { chunk = child; continue outer } + h -= ch; + n += child.chunkSize(); + } + return n + } while (!chunk.lines) + var i = 0; + for (; i < chunk.lines.length; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) { break } + h -= lh; + } + return n + i + } + + function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)) + } + + // A Pos instance represents a position within the text. + function Pos(line, ch, sticky) { + if ( sticky === void 0 ) sticky = null; + + if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } + this.line = line; + this.ch = ch; + this.sticky = sticky; + } + + // Compare two positions, return 0 if they are the same, a negative + // number when a is less, and a positive number otherwise. + function cmp(a, b) { return a.line - b.line || a.ch - b.ch } + + function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } + + function copyPos(x) {return Pos(x.line, x.ch)} + function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } + function minPos(a, b) { return cmp(a, b) < 0 ? a : b } + + // Most of the external API clips given positions to make sure they + // actually exist within the document. + function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} + function clipPos(doc, pos) { + if (pos.line < doc.first) { return Pos(doc.first, 0) } + var last = doc.first + doc.size - 1; + if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } + return clipToLen(pos, getLine(doc, pos.line).text.length) + } + function clipToLen(pos, linelen) { + var ch = pos.ch; + if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } + else if (ch < 0) { return Pos(pos.line, 0) } + else { return pos } + } + function clipPosArray(doc, array) { + var out = []; + for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); } + return out + } + + var SavedContext = function(state, lookAhead) { + this.state = state; + this.lookAhead = lookAhead; + }; + + var Context = function(doc, state, line, lookAhead) { + this.state = state; + this.doc = doc; + this.line = line; + this.maxLookAhead = lookAhead || 0; + this.baseTokens = null; + this.baseTokenPos = 1; + }; + + Context.prototype.lookAhead = function (n) { + var line = this.doc.getLine(this.line + n); + if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; } + return line + }; + + Context.prototype.baseToken = function (n) { + var this$1 = this; + + if (!this.baseTokens) { return null } + while (this.baseTokens[this.baseTokenPos] <= n) + { this$1.baseTokenPos += 2; } + var type = this.baseTokens[this.baseTokenPos + 1]; + return {type: type && type.replace(/( |^)overlay .*/, ""), + size: this.baseTokens[this.baseTokenPos] - n} + }; + + Context.prototype.nextLine = function () { + this.line++; + if (this.maxLookAhead > 0) { this.maxLookAhead--; } + }; + + Context.fromSaved = function (doc, saved, line) { + if (saved instanceof SavedContext) + { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) } + else + { return new Context(doc, copyState(doc.mode, saved), line) } + }; + + Context.prototype.save = function (copy) { + var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state; + return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state + }; + + + // Compute a style array (an array starting with a mode generation + // -- for invalidation -- followed by pairs of end positions and + // style strings), which is used to highlight the tokens on the + // line. + function highlightLine(cm, line, context, forceToEnd) { + // A styles array always starts with a number identifying the + // mode/overlays that it is based on (for easy invalidation). + var st = [cm.state.modeGen], lineClasses = {}; + // Compute the base array of styles + runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); }, + lineClasses, forceToEnd); + var state = context.state; + + // Run overlays, adjust style array. + var loop = function ( o ) { + context.baseTokens = st; + var overlay = cm.state.overlays[o], i = 1, at = 0; + context.state = true; + runMode(cm, line.text, overlay.mode, context, function (end, style) { + var start = i; + // Ensure there's a token end at the current position, and that i points at it + while (at < end) { + var i_end = st[i]; + if (i_end > end) + { st.splice(i, 1, end, st[i+1], i_end); } + i += 2; + at = Math.min(end, i_end); + } + if (!style) { return } + if (overlay.opaque) { + st.splice(start, i - start, end, "overlay " + style); + i = start + 2; + } else { + for (; start < i; start += 2) { + var cur = st[start+1]; + st[start+1] = (cur ? cur + " " : "") + "overlay " + style; + } + } + }, lineClasses); + context.state = state; + context.baseTokens = null; + context.baseTokenPos = 1; + }; + + for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); + + return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} + } + + function getLineStyles(cm, line, updateFrontier) { + if (!line.styles || line.styles[0] != cm.state.modeGen) { + var context = getContextBefore(cm, lineNo(line)); + var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state); + var result = highlightLine(cm, line, context); + if (resetState) { context.state = resetState; } + line.stateAfter = context.save(!resetState); + line.styles = result.styles; + if (result.classes) { line.styleClasses = result.classes; } + else if (line.styleClasses) { line.styleClasses = null; } + if (updateFrontier === cm.doc.highlightFrontier) + { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); } + } + return line.styles + } + + function getContextBefore(cm, n, precise) { + var doc = cm.doc, display = cm.display; + if (!doc.mode.startState) { return new Context(doc, true, n) } + var start = findStartLine(cm, n, precise); + var saved = start > doc.first && getLine(doc, start - 1).stateAfter; + var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start); + + doc.iter(start, n, function (line) { + processLine(cm, line.text, context); + var pos = context.line; + line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null; + context.nextLine(); + }); + if (precise) { doc.modeFrontier = context.line; } + return context + } + + // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. Used for lines that + // aren't currently visible. + function processLine(cm, text, context, startAt) { + var mode = cm.doc.mode; + var stream = new StringStream(text, cm.options.tabSize, context); + stream.start = stream.pos = startAt || 0; + if (text == "") { callBlankLine(mode, context.state); } + while (!stream.eol()) { + readToken(mode, stream, context.state); + stream.start = stream.pos; + } + } + + function callBlankLine(mode, state) { + if (mode.blankLine) { return mode.blankLine(state) } + if (!mode.innerMode) { return } + var inner = innerMode(mode, state); + if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } + } + + function readToken(mode, stream, state, inner) { + for (var i = 0; i < 10; i++) { + if (inner) { inner[0] = innerMode(mode, state).mode; } + var style = mode.token(stream, state); + if (stream.pos > stream.start) { return style } + } + throw new Error("Mode " + mode.name + " failed to advance stream.") + } + + var Token = function(stream, type, state) { + this.start = stream.start; this.end = stream.pos; + this.string = stream.current(); + this.type = type || null; + this.state = state; + }; + + // Utility for getTokenAt and getLineTokens + function takeToken(cm, pos, precise, asArray) { + var doc = cm.doc, mode = doc.mode, style; + pos = clipPos(doc, pos); + var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise); + var stream = new StringStream(line.text, cm.options.tabSize, context), tokens; + if (asArray) { tokens = []; } + while ((asArray || stream.pos < pos.ch) && !stream.eol()) { + stream.start = stream.pos; + style = readToken(mode, stream, context.state); + if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); } + } + return asArray ? tokens : new Token(stream, style, context.state) + } + + function extractLineClasses(type, output) { + if (type) { for (;;) { + var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); + if (!lineClass) { break } + type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); + var prop = lineClass[1] ? "bgClass" : "textClass"; + if (output[prop] == null) + { output[prop] = lineClass[2]; } + else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) + { output[prop] += " " + lineClass[2]; } + } } + return type + } + + // Run the given mode's parser over a line, calling f for each token. + function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) { + var flattenSpans = mode.flattenSpans; + if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; } + var curStart = 0, curStyle = null; + var stream = new StringStream(text, cm.options.tabSize, context), style; + var inner = cm.options.addModeClass && [null]; + if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); } + while (!stream.eol()) { + if (stream.pos > cm.options.maxHighlightLength) { + flattenSpans = false; + if (forceToEnd) { processLine(cm, text, context, stream.pos); } + stream.pos = text.length; + style = null; + } else { + style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses); + } + if (inner) { + var mName = inner[0].name; + if (mName) { style = "m-" + (style ? mName + " " + style : mName); } + } + if (!flattenSpans || curStyle != style) { + while (curStart < stream.start) { + curStart = Math.min(stream.start, curStart + 5000); + f(curStart, curStyle); + } + curStyle = style; + } + stream.start = stream.pos; + } + while (curStart < stream.pos) { + // Webkit seems to refuse to render text nodes longer than 57444 + // characters, and returns inaccurate measurements in nodes + // starting around 5000 chars. + var pos = Math.min(stream.pos, curStart + 5000); + f(pos, curStyle); + curStart = pos; + } + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(cm, n, precise) { + var minindent, minline, doc = cm.doc; + var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); + for (var search = n; search > lim; --search) { + if (search <= doc.first) { return doc.first } + var line = getLine(doc, search - 1), after = line.stateAfter; + if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier)) + { return search } + var indented = countColumn(line.text, null, cm.options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline + } + + function retreatFrontier(doc, n) { + doc.modeFrontier = Math.min(doc.modeFrontier, n); + if (doc.highlightFrontier < n - 10) { return } + var start = doc.first; + for (var line = n - 1; line > start; line--) { + var saved = getLine(doc, line).stateAfter; + // change is on 3 + // state on line 1 looked ahead 2 -- so saw 3 + // test 1 + 2 < 3 should cover this + if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) { + start = line + 1; + break + } + } + doc.highlightFrontier = Math.min(doc.highlightFrontier, start); + } + + // Optimize some code when these features are not used. + var sawReadOnlySpans = false, sawCollapsedSpans = false; + + function seeReadOnlySpans() { + sawReadOnlySpans = true; + } + + function seeCollapsedSpans() { + sawCollapsedSpans = true; + } + + // TEXTMARKER SPANS + + function MarkedSpan(marker, from, to) { + this.marker = marker; + this.from = from; this.to = to; + } + + // Search an array of spans for a span matching the given marker. + function getMarkedSpanFor(spans, marker) { + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) { return span } + } } + } + // Remove a span from an array, returning undefined if no spans are + // left (we don't store arrays for lines without spans). + function removeMarkedSpan(spans, span) { + var r; + for (var i = 0; i < spans.length; ++i) + { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } } + return r + } + // Add a span to a line. + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + span.marker.attachLine(line); + } + + // Used for the algorithm that adjusts markers for a change in the + // document. These functions cut an array of spans at a given + // character position, returning an array of remaining chunks (or + // undefined if nothing remains). + function markedSpansBefore(old, startCh, isInsert) { + var nw; + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); + } + } } + return nw + } + function markedSpansAfter(old, endCh, isInsert) { + var nw; + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, + span.to == null ? null : span.to - endCh)); + } + } } + return nw + } + + // Given a change object, compute the new set of marker spans that + // cover the line in which the change took place. Removes spans + // entirely within the change, reconnects spans belonging to the + // same marker that appear on both sides of the change, and cuts off + // spans partially within the change. Returns an array of span + // arrays with one element for each line in (after) the change. + function stretchSpansOverChange(doc, change) { + if (change.full) { return null } + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; + if (!oldFirst && !oldLast) { return null } + + var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); + + // Next, merge those two ends + var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) { span.to = startCh; } + else if (sameLine) { span.to = found.to == null ? null : found.to + offset; } + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i$1 = 0; i$1 < last.length; ++i$1) { + var span$1 = last[i$1]; + if (span$1.to != null) { span$1.to += offset; } + if (span$1.from == null) { + var found$1 = getMarkedSpanFor(first, span$1.marker); + if (!found$1) { + span$1.from = offset; + if (sameLine) { (first || (first = [])).push(span$1); } + } + } else { + span$1.from += offset; + if (sameLine) { (first || (first = [])).push(span$1); } + } + } + } + // Make sure we didn't create any zero-length spans + if (first) { first = clearEmptySpans(first); } + if (last && last != first) { last = clearEmptySpans(last); } + + var newMarkers = [first]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, gapMarkers; + if (gap > 0 && first) + { for (var i$2 = 0; i$2 < first.length; ++i$2) + { if (first[i$2].to == null) + { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } } + for (var i$3 = 0; i$3 < gap; ++i$3) + { newMarkers.push(gapMarkers); } + newMarkers.push(last); + } + return newMarkers + } + + // Remove spans that are empty and don't have a clearWhenEmpty + // option of false. + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) + { spans.splice(i--, 1); } + } + if (!spans.length) { return null } + return spans + } + + // Used to 'clip' out readOnly ranges when making a change. + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function (line) { + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + { (markers || (markers = [])).push(mark); } + } } + }); + if (!markers) { return null } + var parts = [{from: from, to: to}]; + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], m = mk.find(0); + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } + var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); + if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) + { newParts.push({from: p.from, to: m.from}); } + if (dto > 0 || !mk.inclusiveRight && !dto) + { newParts.push({from: m.to, to: p.to}); } + parts.splice.apply(parts, newParts); + j += newParts.length - 3; + } + } + return parts + } + + // Connect or disconnect spans from a line. + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.detachLine(line); } + line.markedSpans = null; + } + function attachMarkedSpans(line, spans) { + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.attachLine(line); } + line.markedSpans = spans; + } + + // Helpers used when computing which overlapping collapsed span + // counts as the larger one. + function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } + function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } + + // Returns a number indicating which of two overlapping collapsed + // spans is larger (and thus includes the other). Falls back to + // comparing ids when the spans cover exactly the same range. + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length; + if (lenDiff != 0) { return lenDiff } + var aPos = a.find(), bPos = b.find(); + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); + if (fromCmp) { return -fromCmp } + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); + if (toCmp) { return toCmp } + return b.id - a.id + } + + // Find out whether a line ends or starts in a collapsed span. If + // so, return the marker for that span. + function collapsedSpanAtSide(line, start) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) + { found = sp.marker; } + } } + return found + } + function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } + function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } + + function collapsedSpanAround(line, ch) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) { for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; } + } } + return found + } + + // Test whether there exists a collapsed span that partially + // overlaps (covers the start or end, but not both) of a new span. + // Such overlap is not allowed. + function conflictingCollapsedRange(doc, lineNo$$1, from, to, marker) { + var line = getLine(doc, lineNo$$1); + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) { for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (!sp.marker.collapsed) { continue } + var found = sp.marker.find(0); + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } + if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || + fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) + { return true } + } } + } + + // A visual line is a line as drawn on the screen. Folding, for + // example, can cause multiple logical lines to appear on the same + // visual line. This finds the start of the visual line that the + // given line is part of (usually that is the line itself). + function visualLine(line) { + var merged; + while (merged = collapsedSpanAtStart(line)) + { line = merged.find(-1, true).line; } + return line + } + + function visualLineEnd(line) { + var merged; + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line; } + return line + } + + // Returns an array of logical lines that continue the visual line + // started by the argument, or undefined if there are no such lines. + function visualLineContinued(line) { + var merged, lines; + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line + ;(lines || (lines = [])).push(line); + } + return lines + } + + // Get the line number of the start of the visual line that the + // given line number is part of. + function visualLineNo(doc, lineN) { + var line = getLine(doc, lineN), vis = visualLine(line); + if (line == vis) { return lineN } + return lineNo(vis) + } + + // Get the line number of the start of the next visual line after + // the given line. + function visualLineEndNo(doc, lineN) { + if (lineN > doc.lastLine()) { return lineN } + var line = getLine(doc, lineN), merged; + if (!lineIsHidden(doc, line)) { return lineN } + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line; } + return lineNo(line) + 1 + } + + // Compute whether a line is hidden. Lines count as hidden when they + // are part of a visual line that starts with another line, or when + // they are entirely covered by collapsed, non-widget span. + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) { continue } + if (sp.from == null) { return true } + if (sp.marker.widgetNode) { continue } + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) + { return true } + } } + } + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find(1, true); + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) + } + if (span.marker.inclusiveRight && span.to == line.text.length) + { return true } + for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && + (sp.to == null || sp.to != span.from) && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(doc, line, sp)) { return true } + } + } + + // Find the height above the given line. + function heightAtLine(lineObj) { + lineObj = visualLine(lineObj); + + var h = 0, chunk = lineObj.parent; + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + if (line == lineObj) { break } + else { h += line.height; } + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i$1 = 0; i$1 < p.children.length; ++i$1) { + var cur = p.children[i$1]; + if (cur == chunk) { break } + else { h += cur.height; } + } + } + return h + } + + // Compute the character length of a line, taking into account + // collapsed ranges (see markText) that might hide parts, and join + // other lines onto it. + function lineLength(line) { + if (line.height == 0) { return 0 } + var len = line.text.length, merged, cur = line; + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(0, true); + cur = found.from.line; + len += found.from.ch - found.to.ch; + } + cur = line; + while (merged = collapsedSpanAtEnd(cur)) { + var found$1 = merged.find(0, true); + len -= cur.text.length - found$1.from.ch; + cur = found$1.to.line; + len += cur.text.length - found$1.to.ch; + } + return len + } + + // Find the longest line in the document. + function findMaxLine(cm) { + var d = cm.display, doc = cm.doc; + d.maxLine = getLine(doc, doc.first); + d.maxLineLength = lineLength(d.maxLine); + d.maxLineChanged = true; + doc.iter(function (line) { + var len = lineLength(line); + if (len > d.maxLineLength) { + d.maxLineLength = len; + d.maxLine = line; + } + }); + } + + // LINE DATA STRUCTURE + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + var Line = function(text, markedSpans, estimateHeight) { + this.text = text; + attachMarkedSpans(this, markedSpans); + this.height = estimateHeight ? estimateHeight(this) : 1; + }; + + Line.prototype.lineNo = function () { return lineNo(this) }; + eventMixin(Line); + + // Change the content (text, markers) of a line. Automatically + // invalidates cached information and tries to re-estimate the + // line's height. + function updateLine(line, text, markedSpans, estimateHeight) { + line.text = text; + if (line.stateAfter) { line.stateAfter = null; } + if (line.styles) { line.styles = null; } + if (line.order != null) { line.order = null; } + detachMarkedSpans(line); + attachMarkedSpans(line, markedSpans); + var estHeight = estimateHeight ? estimateHeight(line) : 1; + if (estHeight != line.height) { updateLineHeight(line, estHeight); } + } + + // Detach a line from the document tree and its markers. + function cleanUpLine(line) { + line.parent = null; + detachMarkedSpans(line); + } + + // Convert a style as returned by a mode (either null, or a string + // containing one or more styles) to a CSS style. This is cached, + // and also looks for line-wide styles. + var styleToClassCache = {}, styleToClassCacheWithMode = {}; + function interpretTokenStyle(style, options) { + if (!style || /^\s*$/.test(style)) { return null } + var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; + return cache[style] || + (cache[style] = style.replace(/\S+/g, "cm-$&")) + } + + // Render the DOM representation of the text of a line. Also builds + // up a 'line map', which points at the DOM nodes that represent + // specific stretches of text, and is used by the measuring code. + // The returned object contains the DOM node, this map, and + // information about line-wide styles that were set by the mode. + function buildLineContent(cm, lineView) { + // The padding-right forces the element to have a 'border', which + // is needed on Webkit to be able to get line-level bounding + // rectangles for it (in measureChar). + var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null); + var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content, + col: 0, pos: 0, cm: cm, + trailingSpace: false, + splitSpaces: cm.getOption("lineWrapping")}; + lineView.measure = {}; + + // Iterate over the logical lines that make up this visual line. + for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { + var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0); + builder.pos = 0; + builder.addToken = buildToken; + // Optionally wire in some hacks into the token-rendering + // algorithm, to deal with browser quirks. + if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) + { builder.addToken = buildTokenBadBidi(builder.addToken, order); } + builder.map = []; + var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); + insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); + if (line.styleClasses) { + if (line.styleClasses.bgClass) + { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); } + if (line.styleClasses.textClass) + { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); } + } + + // Ensure at least a single node is present, for measuring. + if (builder.map.length == 0) + { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); } + + // Store the map and a cache object for the current logical line + if (i == 0) { + lineView.measure.map = builder.map; + lineView.measure.cache = {}; + } else { + (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) + ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}); + } + } + + // See issue #2901 + if (webkit) { + var last = builder.content.lastChild; + if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) + { builder.content.className = "cm-tab-wrap-hack"; } + } + + signal(cm, "renderLine", cm, lineView.line, builder.pre); + if (builder.pre.className) + { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); } + + return builder + } + + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + ch.charCodeAt(0).toString(16); + token.setAttribute("aria-label", token.title); + return token + } + + // Build up the DOM representation for a single token, and add it to + // the line map. Takes care to render special characters separately. + function buildToken(builder, text, style, startStyle, endStyle, css, attributes) { + if (!text) { return } + var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text; + var special = builder.cm.state.specialChars, mustWrap = false; + var content; + if (!special.test(text)) { + builder.col += text.length; + content = document.createTextNode(displayText); + builder.map.push(builder.pos, builder.pos + text.length, content); + if (ie && ie_version < 9) { mustWrap = true; } + builder.pos += text.length; + } else { + content = document.createDocumentFragment(); + var pos = 0; + while (true) { + special.lastIndex = pos; + var m = special.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + if (skipped) { + var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); + if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); } + else { content.appendChild(txt); } + builder.map.push(builder.pos, builder.pos + skipped, txt); + builder.col += skipped; + builder.pos += skipped; + } + if (!m) { break } + pos += skipped + 1; + var txt$1 = (void 0); + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; + txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + txt$1.setAttribute("role", "presentation"); + txt$1.setAttribute("cm-text", "\t"); + builder.col += tabWidth; + } else if (m[0] == "\r" || m[0] == "\n") { + txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); + txt$1.setAttribute("cm-text", m[0]); + builder.col += 1; + } else { + txt$1 = builder.cm.options.specialCharPlaceholder(m[0]); + txt$1.setAttribute("cm-text", m[0]); + if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); } + else { content.appendChild(txt$1); } + builder.col += 1; + } + builder.map.push(builder.pos, builder.pos + 1, txt$1); + builder.pos++; + } + } + builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32; + if (style || startStyle || endStyle || mustWrap || css) { + var fullStyle = style || ""; + if (startStyle) { fullStyle += startStyle; } + if (endStyle) { fullStyle += endStyle; } + var token = elt("span", [content], fullStyle, css); + if (attributes) { + for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class") + { token.setAttribute(attr, attributes[attr]); } } + } + return builder.content.appendChild(token) + } + builder.content.appendChild(content); + } + + // Change some spaces to NBSP to prevent the browser from collapsing + // trailing spaces at the end of a line when rendering text (issue #1362). + function splitSpaces(text, trailingBefore) { + if (text.length > 1 && !/ /.test(text)) { return text } + var spaceBefore = trailingBefore, result = ""; + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i); + if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) + { ch = "\u00a0"; } + result += ch; + spaceBefore = ch == " "; + } + return result + } + + // Work around nonsense dimensions being reported for stretches of + // right-to-left text. + function buildTokenBadBidi(inner, order) { + return function (builder, text, style, startStyle, endStyle, css, attributes) { + style = style ? style + " cm-force-border" : "cm-force-border"; + var start = builder.pos, end = start + text.length; + for (;;) { + // Find the part that overlaps with the start of this text + var part = (void 0); + for (var i = 0; i < order.length; i++) { + part = order[i]; + if (part.to > start && part.from <= start) { break } + } + if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) } + inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes); + startStyle = null; + text = text.slice(part.to - start); + start = part.to; + } + } + } + + function buildCollapsedSpan(builder, size, marker, ignoreWidget) { + var widget = !ignoreWidget && marker.widgetNode; + if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); } + if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { + if (!widget) + { widget = builder.content.appendChild(document.createElement("span")); } + widget.setAttribute("cm-marker", marker.id); + } + if (widget) { + builder.cm.display.input.setUneditable(widget); + builder.content.appendChild(widget); + } + builder.pos += size; + builder.trailingSpace = false; + } + + // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + function insertLineContent(line, builder, styles) { + var spans = line.markedSpans, allText = line.text, at = 0; + if (!spans) { + for (var i$1 = 1; i$1 < styles.length; i$1+=2) + { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); } + return + } + + var len = allText.length, pos = 0, i = 1, text = "", style, css; + var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes; + for (;;) { + if (nextChange == pos) { // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = css = ""; + attributes = null; + collapsed = null; nextChange = Infinity; + var foundBookmarks = [], endStyles = (void 0); + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], m = sp.marker; + if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { + foundBookmarks.push(m); + } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { + if (sp.to != null && sp.to != pos && nextChange > sp.to) { + nextChange = sp.to; + spanEndStyle = ""; + } + if (m.className) { spanStyle += " " + m.className; } + if (m.css) { css = (css ? css + ";" : "") + m.css; } + if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; } + if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); } + // support for the old title property + // https://github.com/codemirror/CodeMirror/pull/5673 + if (m.title) { (attributes || (attributes = {})).title = m.title; } + if (m.attributes) { + for (var attr in m.attributes) + { (attributes || (attributes = {}))[attr] = m.attributes[attr]; } + } + if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) + { collapsed = sp; } + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from; + } + } + if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) + { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } } + + if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) + { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } } + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, + collapsed.marker, collapsed.from == null); + if (collapsed.to == null) { return } + if (collapsed.to == pos) { collapsed = false; } + } + } + if (pos >= len) { break } + + var upto = Math.min(len, nextChange); + while (true) { + if (text) { + var end = pos + text.length; + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text; + builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes); + } + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} + pos = end; + spanStartStyle = ""; + } + text = allText.slice(at, at = styles[i++]); + style = interpretTokenStyle(styles[i++], builder.cm.options); + } + } + } + + + // These objects are used to represent the visible (currently drawn) + // part of the document. A LineView may correspond to multiple + // logical lines, if those are connected by collapsed ranges. + function LineView(doc, line, lineN) { + // The starting line + this.line = line; + // Continuing lines, if any + this.rest = visualLineContinued(line); + // Number of logical lines in this visual line + this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; + this.node = this.text = null; + this.hidden = lineIsHidden(doc, line); + } + + // Create a range of LineView objects for the given lines. + function buildViewArray(cm, from, to) { + var array = [], nextPos; + for (var pos = from; pos < to; pos = nextPos) { + var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); + nextPos = pos + view.size; + array.push(view); + } + return array + } + + var operationGroup = null; + + function pushOperation(op) { + if (operationGroup) { + operationGroup.ops.push(op); + } else { + op.ownsGroup = operationGroup = { + ops: [op], + delayedCallbacks: [] + }; + } + } + + function fireCallbacksForOps(group) { + // Calls delayed callbacks and cursorActivity handlers until no + // new ones appear + var callbacks = group.delayedCallbacks, i = 0; + do { + for (; i < callbacks.length; i++) + { callbacks[i].call(null); } + for (var j = 0; j < group.ops.length; j++) { + var op = group.ops[j]; + if (op.cursorActivityHandlers) + { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) + { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } } + } + } while (i < callbacks.length) + } + + function finishOperation(op, endCb) { + var group = op.ownsGroup; + if (!group) { return } + + try { fireCallbacksForOps(group); } + finally { + operationGroup = null; + endCb(group); + } + } + + var orphanDelayedCallbacks = null; + + // Often, we want to signal events at a point where we are in the + // middle of some work, but don't want the handler to start calling + // other methods on the editor, which might be in an inconsistent + // state or simply not expect any other events to happen. + // signalLater looks whether there are any handlers, and schedules + // them to be executed when the last operation ends, or, if no + // operation is active, when a timeout fires. + function signalLater(emitter, type /*, values...*/) { + var arr = getHandlers(emitter, type); + if (!arr.length) { return } + var args = Array.prototype.slice.call(arguments, 2), list; + if (operationGroup) { + list = operationGroup.delayedCallbacks; + } else if (orphanDelayedCallbacks) { + list = orphanDelayedCallbacks; + } else { + list = orphanDelayedCallbacks = []; + setTimeout(fireOrphanDelayed, 0); + } + var loop = function ( i ) { + list.push(function () { return arr[i].apply(null, args); }); + }; + + for (var i = 0; i < arr.length; ++i) + loop( i ); + } + + function fireOrphanDelayed() { + var delayed = orphanDelayedCallbacks; + orphanDelayedCallbacks = null; + for (var i = 0; i < delayed.length; ++i) { delayed[i](); } + } + + // When an aspect of a line changes, a string is added to + // lineView.changes. This updates the relevant part of the line's + // DOM structure. + function updateLineForChanges(cm, lineView, lineN, dims) { + for (var j = 0; j < lineView.changes.length; j++) { + var type = lineView.changes[j]; + if (type == "text") { updateLineText(cm, lineView); } + else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); } + else if (type == "class") { updateLineClasses(cm, lineView); } + else if (type == "widget") { updateLineWidgets(cm, lineView, dims); } + } + lineView.changes = null; + } + + // Lines with gutter elements, widgets or a background class need to + // be wrapped, and have the extra elements added to the wrapper div + function ensureLineWrapped(lineView) { + if (lineView.node == lineView.text) { + lineView.node = elt("div", null, null, "position: relative"); + if (lineView.text.parentNode) + { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); } + lineView.node.appendChild(lineView.text); + if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; } + } + return lineView.node + } + + function updateLineBackground(cm, lineView) { + var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; + if (cls) { cls += " CodeMirror-linebackground"; } + if (lineView.background) { + if (cls) { lineView.background.className = cls; } + else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } + } else if (cls) { + var wrap = ensureLineWrapped(lineView); + lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); + cm.display.input.setUneditable(lineView.background); + } + } + + // Wrapper around buildLineContent which will reuse the structure + // in display.externalMeasured when possible. + function getLineContent(cm, lineView) { + var ext = cm.display.externalMeasured; + if (ext && ext.line == lineView.line) { + cm.display.externalMeasured = null; + lineView.measure = ext.measure; + return ext.built + } + return buildLineContent(cm, lineView) + } + + // Redraw the line's text. Interacts with the background and text + // classes because the mode may output tokens that influence these + // classes. + function updateLineText(cm, lineView) { + var cls = lineView.text.className; + var built = getLineContent(cm, lineView); + if (lineView.text == lineView.node) { lineView.node = built.pre; } + lineView.text.parentNode.replaceChild(built.pre, lineView.text); + lineView.text = built.pre; + if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { + lineView.bgClass = built.bgClass; + lineView.textClass = built.textClass; + updateLineClasses(cm, lineView); + } else if (cls) { + lineView.text.className = cls; + } + } + + function updateLineClasses(cm, lineView) { + updateLineBackground(cm, lineView); + if (lineView.line.wrapClass) + { ensureLineWrapped(lineView).className = lineView.line.wrapClass; } + else if (lineView.node != lineView.text) + { lineView.node.className = ""; } + var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; + lineView.text.className = textClass || ""; + } + + function updateLineGutter(cm, lineView, lineN, dims) { + if (lineView.gutter) { + lineView.node.removeChild(lineView.gutter); + lineView.gutter = null; + } + if (lineView.gutterBackground) { + lineView.node.removeChild(lineView.gutterBackground); + lineView.gutterBackground = null; + } + if (lineView.line.gutterClass) { + var wrap = ensureLineWrapped(lineView); + lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, + ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")); + cm.display.input.setUneditable(lineView.gutterBackground); + wrap.insertBefore(lineView.gutterBackground, lineView.text); + } + var markers = lineView.line.gutterMarkers; + if (cm.options.lineNumbers || markers) { + var wrap$1 = ensureLineWrapped(lineView); + var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")); + cm.display.input.setUneditable(gutterWrap); + wrap$1.insertBefore(gutterWrap, lineView.text); + if (lineView.line.gutterClass) + { gutterWrap.className += " " + lineView.line.gutterClass; } + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) + { lineView.lineNumber = gutterWrap.appendChild( + elt("div", lineNumberFor(cm.options, lineN), + "CodeMirror-linenumber CodeMirror-gutter-elt", + ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); } + if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) { + var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id]; + if (found) + { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", + ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); } + } } + } + } + + function updateLineWidgets(cm, lineView, dims) { + if (lineView.alignable) { lineView.alignable = null; } + for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { + next = node.nextSibling; + if (node.className == "CodeMirror-linewidget") + { lineView.node.removeChild(node); } + } + insertLineWidgets(cm, lineView, dims); + } + + // Build a line's DOM representation from scratch + function buildLineElement(cm, lineView, lineN, dims) { + var built = getLineContent(cm, lineView); + lineView.text = lineView.node = built.pre; + if (built.bgClass) { lineView.bgClass = built.bgClass; } + if (built.textClass) { lineView.textClass = built.textClass; } + + updateLineClasses(cm, lineView); + updateLineGutter(cm, lineView, lineN, dims); + insertLineWidgets(cm, lineView, dims); + return lineView.node + } + + // A lineView may contain multiple logical lines (when merged by + // collapsed spans). The widgets for all of them need to be drawn. + function insertLineWidgets(cm, lineView, dims) { + insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); + if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) + { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } } + } + + function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { + if (!line.widgets) { return } + var wrap = ensureLineWrapped(lineView); + for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); + if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); } + positionLineWidget(widget, node, lineView, dims); + cm.display.input.setUneditable(node); + if (allowAbove && widget.above) + { wrap.insertBefore(node, lineView.gutter || lineView.text); } + else + { wrap.appendChild(node); } + signalLater(widget, "redraw"); + } + } + + function positionLineWidget(widget, node, lineView, dims) { + if (widget.noHScroll) { + (lineView.alignable || (lineView.alignable = [])).push(node); + var width = dims.wrapperWidth; + node.style.left = dims.fixedPos + "px"; + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth; + node.style.paddingLeft = dims.gutterTotalWidth + "px"; + } + node.style.width = width + "px"; + } + if (widget.coverGutter) { + node.style.zIndex = 5; + node.style.position = "relative"; + if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; } + } + } + + function widgetHeight(widget) { + if (widget.height != null) { return widget.height } + var cm = widget.doc.cm; + if (!cm) { return 0 } + if (!contains(document.body, widget.node)) { + var parentStyle = "position: relative;"; + if (widget.coverGutter) + { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; } + if (widget.noHScroll) + { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; } + removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); + } + return widget.height = widget.node.parentNode.offsetHeight + } + + // Return true when the given mouse event happened in a widget + function eventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { + if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || + (n.parentNode == display.sizer && n != display.mover)) + { return true } + } + } + + // POSITION MEASUREMENT + + function paddingTop(display) {return display.lineSpace.offsetTop} + function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} + function paddingH(display) { + if (display.cachedPaddingH) { return display.cachedPaddingH } + var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like")); + var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; + var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; + if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; } + return data + } + + function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } + function displayWidth(cm) { + return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth + } + function displayHeight(cm) { + return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight + } + + // Ensure the lineView.wrapping.heights array is populated. This is + // an array of bottom offsets for the lines that make up a drawn + // line. When lineWrapping is on, there might be more than one + // height. + function ensureLineHeights(cm, lineView, rect) { + var wrapping = cm.options.lineWrapping; + var curWidth = wrapping && displayWidth(cm); + if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { + var heights = lineView.measure.heights = []; + if (wrapping) { + lineView.measure.width = curWidth; + var rects = lineView.text.firstChild.getClientRects(); + for (var i = 0; i < rects.length - 1; i++) { + var cur = rects[i], next = rects[i + 1]; + if (Math.abs(cur.bottom - next.bottom) > 2) + { heights.push((cur.bottom + next.top) / 2 - rect.top); } + } + } + heights.push(rect.bottom - rect.top); + } + } + + // Find a line map (mapping character offsets to text nodes) and a + // measurement cache for the given line number. (A line view might + // contain multiple lines when collapsed ranges are present.) + function mapFromLineView(lineView, line, lineN) { + if (lineView.line == line) + { return {map: lineView.measure.map, cache: lineView.measure.cache} } + for (var i = 0; i < lineView.rest.length; i++) + { if (lineView.rest[i] == line) + { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } + for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) + { if (lineNo(lineView.rest[i$1]) > lineN) + { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } + } + + // Render a line into the hidden node display.externalMeasured. Used + // when measurement is needed for a line that's not in the viewport. + function updateExternalMeasurement(cm, line) { + line = visualLine(line); + var lineN = lineNo(line); + var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); + view.lineN = lineN; + var built = view.built = buildLineContent(cm, view); + view.text = built.pre; + removeChildrenAndAdd(cm.display.lineMeasure, built.pre); + return view + } + + // Get a {top, bottom, left, right} box (in line-local coordinates) + // for a given character. + function measureChar(cm, line, ch, bias) { + return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) + } + + // Find a line view that corresponds to the given line number. + function findViewForLine(cm, lineN) { + if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) + { return cm.display.view[findViewIndex(cm, lineN)] } + var ext = cm.display.externalMeasured; + if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) + { return ext } + } + + // Measurement can be split in two steps, the set-up work that + // applies to the whole line, and the measurement of the actual + // character. Functions like coordsChar, that need to do a lot of + // measurements in a row, can thus ensure that the set-up work is + // only done once. + function prepareMeasureForLine(cm, line) { + var lineN = lineNo(line); + var view = findViewForLine(cm, lineN); + if (view && !view.text) { + view = null; + } else if (view && view.changes) { + updateLineForChanges(cm, view, lineN, getDimensions(cm)); + cm.curOp.forceUpdate = true; + } + if (!view) + { view = updateExternalMeasurement(cm, line); } + + var info = mapFromLineView(view, line, lineN); + return { + line: line, view: view, rect: null, + map: info.map, cache: info.cache, before: info.before, + hasHeights: false + } + } + + // Given a prepared measurement object, measures the position of an + // actual character (or fetches it from the cache). + function measureCharPrepared(cm, prepared, ch, bias, varHeight) { + if (prepared.before) { ch = -1; } + var key = ch + (bias || ""), found; + if (prepared.cache.hasOwnProperty(key)) { + found = prepared.cache[key]; + } else { + if (!prepared.rect) + { prepared.rect = prepared.view.text.getBoundingClientRect(); } + if (!prepared.hasHeights) { + ensureLineHeights(cm, prepared.view, prepared.rect); + prepared.hasHeights = true; + } + found = measureCharInner(cm, prepared, ch, bias); + if (!found.bogus) { prepared.cache[key] = found; } + } + return {left: found.left, right: found.right, + top: varHeight ? found.rtop : found.top, + bottom: varHeight ? found.rbottom : found.bottom} + } + + var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; + + function nodeAndOffsetInLineMap(map$$1, ch, bias) { + var node, start, end, collapse, mStart, mEnd; + // First, search the line map for the text node corresponding to, + // or closest to, the target character. + for (var i = 0; i < map$$1.length; i += 3) { + mStart = map$$1[i]; + mEnd = map$$1[i + 1]; + if (ch < mStart) { + start = 0; end = 1; + collapse = "left"; + } else if (ch < mEnd) { + start = ch - mStart; + end = start + 1; + } else if (i == map$$1.length - 3 || ch == mEnd && map$$1[i + 3] > ch) { + end = mEnd - mStart; + start = end - 1; + if (ch >= mEnd) { collapse = "right"; } + } + if (start != null) { + node = map$$1[i + 2]; + if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) + { collapse = bias; } + if (bias == "left" && start == 0) + { while (i && map$$1[i - 2] == map$$1[i - 3] && map$$1[i - 1].insertLeft) { + node = map$$1[(i -= 3) + 2]; + collapse = "left"; + } } + if (bias == "right" && start == mEnd - mStart) + { while (i < map$$1.length - 3 && map$$1[i + 3] == map$$1[i + 4] && !map$$1[i + 5].insertLeft) { + node = map$$1[(i += 3) + 2]; + collapse = "right"; + } } + break + } + } + return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} + } + + function getUsefulRect(rects, bias) { + var rect = nullRect; + if (bias == "left") { for (var i = 0; i < rects.length; i++) { + if ((rect = rects[i]).left != rect.right) { break } + } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { + if ((rect = rects[i$1]).left != rect.right) { break } + } } + return rect + } + + function measureCharInner(cm, prepared, ch, bias) { + var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); + var node = place.node, start = place.start, end = place.end, collapse = place.collapse; + + var rect; + if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. + for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned + while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; } + while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; } + if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) + { rect = node.parentNode.getBoundingClientRect(); } + else + { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); } + if (rect.left || rect.right || start == 0) { break } + end = start; + start = start - 1; + collapse = "right"; + } + if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); } + } else { // If it is a widget, simply get the box for the whole widget. + if (start > 0) { collapse = bias = "right"; } + var rects; + if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) + { rect = rects[bias == "right" ? rects.length - 1 : 0]; } + else + { rect = node.getBoundingClientRect(); } + } + if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { + var rSpan = node.parentNode.getClientRects()[0]; + if (rSpan) + { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; } + else + { rect = nullRect; } + } + + var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; + var mid = (rtop + rbot) / 2; + var heights = prepared.view.measure.heights; + var i = 0; + for (; i < heights.length - 1; i++) + { if (mid < heights[i]) { break } } + var top = i ? heights[i - 1] : 0, bot = heights[i]; + var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, + right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, + top: top, bottom: bot}; + if (!rect.left && !rect.right) { result.bogus = true; } + if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } + + return result + } + + // Work around problem with bounding client rects on ranges being + // returned incorrectly when zoomed on IE10 and below. + function maybeUpdateRectForZooming(measure, rect) { + if (!window.screen || screen.logicalXDPI == null || + screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) + { return rect } + var scaleX = screen.logicalXDPI / screen.deviceXDPI; + var scaleY = screen.logicalYDPI / screen.deviceYDPI; + return {left: rect.left * scaleX, right: rect.right * scaleX, + top: rect.top * scaleY, bottom: rect.bottom * scaleY} + } + + function clearLineMeasurementCacheFor(lineView) { + if (lineView.measure) { + lineView.measure.cache = {}; + lineView.measure.heights = null; + if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) + { lineView.measure.caches[i] = {}; } } + } + } + + function clearLineMeasurementCache(cm) { + cm.display.externalMeasure = null; + removeChildren(cm.display.lineMeasure); + for (var i = 0; i < cm.display.view.length; i++) + { clearLineMeasurementCacheFor(cm.display.view[i]); } + } + + function clearCaches(cm) { + clearLineMeasurementCache(cm); + cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; + if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; } + cm.display.lineNumChars = null; + } + + function pageScrollX() { + // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206 + // which causes page_Offset and bounding client rects to use + // different reference viewports and invalidate our calculations. + if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) } + return window.pageXOffset || (document.documentElement || document.body).scrollLeft + } + function pageScrollY() { + if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) } + return window.pageYOffset || (document.documentElement || document.body).scrollTop + } + + function widgetTopHeight(lineObj) { + var height = 0; + if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) + { height += widgetHeight(lineObj.widgets[i]); } } } + return height + } + + // Converts a {top, bottom, left, right} box from line-local + // coordinates into another coordinate system. Context may be one of + // "line", "div" (display.lineDiv), "local"./null (editor), "window", + // or "page". + function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { + if (!includeWidgets) { + var height = widgetTopHeight(lineObj); + rect.top += height; rect.bottom += height; + } + if (context == "line") { return rect } + if (!context) { context = "local"; } + var yOff = heightAtLine(lineObj); + if (context == "local") { yOff += paddingTop(cm.display); } + else { yOff -= cm.display.viewOffset; } + if (context == "page" || context == "window") { + var lOff = cm.display.lineSpace.getBoundingClientRect(); + yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); + var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); + rect.left += xOff; rect.right += xOff; + } + rect.top += yOff; rect.bottom += yOff; + return rect + } + + // Coverts a box from "div" coords to another coordinate system. + // Context may be "window", "page", "div", or "local"./null. + function fromCoordSystem(cm, coords, context) { + if (context == "div") { return coords } + var left = coords.left, top = coords.top; + // First move into "page" coordinate system + if (context == "page") { + left -= pageScrollX(); + top -= pageScrollY(); + } else if (context == "local" || !context) { + var localBox = cm.display.sizer.getBoundingClientRect(); + left += localBox.left; + top += localBox.top; + } + + var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); + return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} + } + + function charCoords(cm, pos, context, lineObj, bias) { + if (!lineObj) { lineObj = getLine(cm.doc, pos.line); } + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) + } + + // Returns a box for a given cursor position, which may have an + // 'other' property containing the position of the secondary cursor + // on a bidi boundary. + // A cursor Pos(line, char, "before") is on the same visual line as `char - 1` + // and after `char - 1` in writing order of `char - 1` + // A cursor Pos(line, char, "after") is on the same visual line as `char` + // and before `char` in writing order of `char` + // Examples (upper-case letters are RTL, lower-case are LTR): + // Pos(0, 1, ...) + // before after + // ab a|b a|b + // aB a|B aB| + // Ab |Ab A|b + // AB B|A B|A + // Every position after the last character on a line is considered to stick + // to the last character on the line. + function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { + lineObj = lineObj || getLine(cm.doc, pos.line); + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } + function get(ch, right) { + var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); + if (right) { m.left = m.right; } else { m.right = m.left; } + return intoCoordSystem(cm, lineObj, m, context) + } + var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky; + if (ch >= lineObj.text.length) { + ch = lineObj.text.length; + sticky = "before"; + } else if (ch <= 0) { + ch = 0; + sticky = "after"; + } + if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } + + function getBidi(ch, partPos, invert) { + var part = order[partPos], right = part.level == 1; + return get(invert ? ch - 1 : ch, right != invert) + } + var partPos = getBidiPartAt(order, ch, sticky); + var other = bidiOther; + var val = getBidi(ch, partPos, sticky == "before"); + if (other != null) { val.other = getBidi(ch, other, sticky != "before"); } + return val + } + + // Used to cheaply estimate the coordinates for a position. Used for + // intermediate scroll updates. + function estimateCoords(cm, pos) { + var left = 0; + pos = clipPos(cm.doc, pos); + if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; } + var lineObj = getLine(cm.doc, pos.line); + var top = heightAtLine(lineObj) + paddingTop(cm.display); + return {left: left, right: left, top: top, bottom: top + lineObj.height} + } + + // Positions returned by coordsChar contain some extra information. + // xRel is the relative x position of the input coordinates compared + // to the found position (so xRel > 0 means the coordinates are to + // the right of the character position, for example). When outside + // is true, that means the coordinates lie outside the line's + // vertical range. + function PosWithInfo(line, ch, sticky, outside, xRel) { + var pos = Pos(line, ch, sticky); + pos.xRel = xRel; + if (outside) { pos.outside = outside; } + return pos + } + + // Compute the character position closest to the given coordinates. + // Input must be lineSpace-local ("div" coordinate system). + function coordsChar(cm, x, y) { + var doc = cm.doc; + y += cm.display.viewOffset; + if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) } + var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; + if (lineN > last) + { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) } + if (x < 0) { x = 0; } + + var lineObj = getLine(doc, lineN); + for (;;) { + var found = coordsCharInner(cm, lineObj, lineN, x, y); + var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0)); + if (!collapsed) { return found } + var rangeEnd = collapsed.find(1); + if (rangeEnd.line == lineN) { return rangeEnd } + lineObj = getLine(doc, lineN = rangeEnd.line); + } + } + + function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { + y -= widgetTopHeight(lineObj); + var end = lineObj.text.length; + var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0); + end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end); + return {begin: begin, end: end} + } + + function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } + var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top; + return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) + } + + // Returns true if the given side of a box is after the given + // coordinates, in top-to-bottom, left-to-right order. + function boxIsAfter(box, x, y, left) { + return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x + } + + function coordsCharInner(cm, lineObj, lineNo$$1, x, y) { + // Move y into line-local coordinate space + y -= heightAtLine(lineObj); + var preparedMeasure = prepareMeasureForLine(cm, lineObj); + // When directly calling `measureCharPrepared`, we have to adjust + // for the widgets at this line. + var widgetHeight$$1 = widgetTopHeight(lineObj); + var begin = 0, end = lineObj.text.length, ltr = true; + + var order = getOrder(lineObj, cm.doc.direction); + // If the line isn't plain left-to-right text, first figure out + // which bidi section the coordinates fall into. + if (order) { + var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) + (cm, lineObj, lineNo$$1, preparedMeasure, order, x, y); + ltr = part.level != 1; + // The awkward -1 offsets are needed because findFirst (called + // on these below) will treat its first bound as inclusive, + // second as exclusive, but we want to actually address the + // characters in the part's range + begin = ltr ? part.from : part.to - 1; + end = ltr ? part.to : part.from - 1; + } + + // A binary search to find the first character whose bounding box + // starts after the coordinates. If we run across any whose box wrap + // the coordinates, store that. + var chAround = null, boxAround = null; + var ch = findFirst(function (ch) { + var box = measureCharPrepared(cm, preparedMeasure, ch); + box.top += widgetHeight$$1; box.bottom += widgetHeight$$1; + if (!boxIsAfter(box, x, y, false)) { return false } + if (box.top <= y && box.left <= x) { + chAround = ch; + boxAround = box; + } + return true + }, begin, end); + + var baseX, sticky, outside = false; + // If a box around the coordinates was found, use that + if (boxAround) { + // Distinguish coordinates nearer to the left or right side of the box + var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr; + ch = chAround + (atStart ? 0 : 1); + sticky = atStart ? "after" : "before"; + baseX = atLeft ? boxAround.left : boxAround.right; + } else { + // (Adjust for extended bound, if necessary.) + if (!ltr && (ch == end || ch == begin)) { ch++; } + // To determine which side to associate with, get the box to the + // left of the character and compare it's vertical position to the + // coordinates + sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : + (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight$$1 <= y) == ltr ? + "after" : "before"; + // Now get accurate coordinates for this place, in order to get a + // base X position + var coords = cursorCoords(cm, Pos(lineNo$$1, ch, sticky), "line", lineObj, preparedMeasure); + baseX = coords.left; + outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0; + } + + ch = skipExtendingChars(lineObj.text, ch, 1); + return PosWithInfo(lineNo$$1, ch, sticky, outside, x - baseX) + } + + function coordsBidiPart(cm, lineObj, lineNo$$1, preparedMeasure, order, x, y) { + // Bidi parts are sorted left-to-right, and in a non-line-wrapping + // situation, we can take this ordering to correspond to the visual + // ordering. This finds the first part whose end is after the given + // coordinates. + var index = findFirst(function (i) { + var part = order[i], ltr = part.level != 1; + return boxIsAfter(cursorCoords(cm, Pos(lineNo$$1, ltr ? part.to : part.from, ltr ? "before" : "after"), + "line", lineObj, preparedMeasure), x, y, true) + }, 0, order.length - 1); + var part = order[index]; + // If this isn't the first part, the part's start is also after + // the coordinates, and the coordinates aren't on the same line as + // that start, move one part back. + if (index > 0) { + var ltr = part.level != 1; + var start = cursorCoords(cm, Pos(lineNo$$1, ltr ? part.from : part.to, ltr ? "after" : "before"), + "line", lineObj, preparedMeasure); + if (boxIsAfter(start, x, y, true) && start.top > y) + { part = order[index - 1]; } + } + return part + } + + function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { + // In a wrapped line, rtl text on wrapping boundaries can do things + // that don't correspond to the ordering in our `order` array at + // all, so a binary search doesn't work, and we want to return a + // part that only spans one line so that the binary search in + // coordsCharInner is safe. As such, we first find the extent of the + // wrapped line, and then do a flat search in which we discard any + // spans that aren't on the line. + var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); + var begin = ref.begin; + var end = ref.end; + if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; } + var part = null, closestDist = null; + for (var i = 0; i < order.length; i++) { + var p = order[i]; + if (p.from >= end || p.to <= begin) { continue } + var ltr = p.level != 1; + var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right; + // Weigh against spans ending before this, so that they are only + // picked if nothing ends after + var dist = endX < x ? x - endX + 1e9 : endX - x; + if (!part || closestDist > dist) { + part = p; + closestDist = dist; + } + } + if (!part) { part = order[order.length - 1]; } + // Clip the part to the wrapped line. + if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; } + if (part.to > end) { part = {from: part.from, to: end, level: part.level}; } + return part + } + + var measureText; + // Compute the default text height. + function textHeight(display) { + if (display.cachedTextHeight != null) { return display.cachedTextHeight } + if (measureText == null) { + measureText = elt("pre", null, "CodeMirror-line-like"); + // Measure a bunch of lines, for browsers that compute + // fractional heights. + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")); + measureText.appendChild(elt("br")); + } + measureText.appendChild(document.createTextNode("x")); + } + removeChildrenAndAdd(display.measure, measureText); + var height = measureText.offsetHeight / 50; + if (height > 3) { display.cachedTextHeight = height; } + removeChildren(display.measure); + return height || 1 + } + + // Compute the default character width. + function charWidth(display) { + if (display.cachedCharWidth != null) { return display.cachedCharWidth } + var anchor = elt("span", "xxxxxxxxxx"); + var pre = elt("pre", [anchor], "CodeMirror-line-like"); + removeChildrenAndAdd(display.measure, pre); + var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; + if (width > 2) { display.cachedCharWidth = width; } + return width || 10 + } + + // Do a bulk-read of the DOM positions and sizes needed to draw the + // view, so that we don't interleave reading and writing to the DOM. + function getDimensions(cm) { + var d = cm.display, left = {}, width = {}; + var gutterLeft = d.gutters.clientLeft; + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + var id = cm.display.gutterSpecs[i].className; + left[id] = n.offsetLeft + n.clientLeft + gutterLeft; + width[id] = n.clientWidth; + } + return {fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth} + } + + // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, + // but using getBoundingClientRect to get a sub-pixel-accurate + // result. + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left + } + + // Returns a function that estimates the height of a line, to use as + // first approximation until the line becomes visible (and is thus + // properly measurable). + function estimateHeight(cm) { + var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; + var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); + return function (line) { + if (lineIsHidden(cm.doc, line)) { return 0 } + + var widgetsHeight = 0; + if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { + if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; } + } } + + if (wrapping) + { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } + else + { return widgetsHeight + th } + } + } + + function estimateLineHeights(cm) { + var doc = cm.doc, est = estimateHeight(cm); + doc.iter(function (line) { + var estHeight = est(line); + if (estHeight != line.height) { updateLineHeight(line, estHeight); } + }); + } + + // Given a mouse event, find the corresponding position. If liberal + // is false, it checks whether a gutter or scrollbar was clicked, + // and returns null if it was. forRect is used by rectangular + // selections, and tries to estimate a character position even for + // coordinates beyond the right of the text. + function posFromMouse(cm, e, liberal, forRect) { + var display = cm.display; + if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } + + var x, y, space = display.lineSpace.getBoundingClientRect(); + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX - space.left; y = e.clientY - space.top; } + catch (e) { return null } + var coords = coordsChar(cm, x, y), line; + if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { + var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; + coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); + } + return coords + } + + // Find the view element corresponding to a given line. Return null + // when the line isn't visible. + function findViewIndex(cm, n) { + if (n >= cm.display.viewTo) { return null } + n -= cm.display.viewFrom; + if (n < 0) { return null } + var view = cm.display.view; + for (var i = 0; i < view.length; i++) { + n -= view[i].size; + if (n < 0) { return i } + } + } + + // Updates the display.view data structure for a given change to the + // document. From and to are in pre-change coordinates. Lendiff is + // the amount of lines added or subtracted by the change. This is + // used for changes that span multiple lines, or change the way + // lines are divided into visual lines. regLineChange (below) + // registers single-line changes. + function regChange(cm, from, to, lendiff) { + if (from == null) { from = cm.doc.first; } + if (to == null) { to = cm.doc.first + cm.doc.size; } + if (!lendiff) { lendiff = 0; } + + var display = cm.display; + if (lendiff && to < display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers > from)) + { display.updateLineNumbers = from; } + + cm.curOp.viewChanged = true; + + if (from >= display.viewTo) { // Change after + if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) + { resetView(cm); } + } else if (to <= display.viewFrom) { // Change before + if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { + resetView(cm); + } else { + display.viewFrom += lendiff; + display.viewTo += lendiff; + } + } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap + resetView(cm); + } else if (from <= display.viewFrom) { // Top overlap + var cut = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cut) { + display.view = display.view.slice(cut.index); + display.viewFrom = cut.lineN; + display.viewTo += lendiff; + } else { + resetView(cm); + } + } else if (to >= display.viewTo) { // Bottom overlap + var cut$1 = viewCuttingPoint(cm, from, from, -1); + if (cut$1) { + display.view = display.view.slice(0, cut$1.index); + display.viewTo = cut$1.lineN; + } else { + resetView(cm); + } + } else { // Gap in the middle + var cutTop = viewCuttingPoint(cm, from, from, -1); + var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cutTop && cutBot) { + display.view = display.view.slice(0, cutTop.index) + .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) + .concat(display.view.slice(cutBot.index)); + display.viewTo += lendiff; + } else { + resetView(cm); + } + } + + var ext = display.externalMeasured; + if (ext) { + if (to < ext.lineN) + { ext.lineN += lendiff; } + else if (from < ext.lineN + ext.size) + { display.externalMeasured = null; } + } + } + + // Register a change to a single line. Type must be one of "text", + // "gutter", "class", "widget" + function regLineChange(cm, line, type) { + cm.curOp.viewChanged = true; + var display = cm.display, ext = cm.display.externalMeasured; + if (ext && line >= ext.lineN && line < ext.lineN + ext.size) + { display.externalMeasured = null; } + + if (line < display.viewFrom || line >= display.viewTo) { return } + var lineView = display.view[findViewIndex(cm, line)]; + if (lineView.node == null) { return } + var arr = lineView.changes || (lineView.changes = []); + if (indexOf(arr, type) == -1) { arr.push(type); } + } + + // Clear the view. + function resetView(cm) { + cm.display.viewFrom = cm.display.viewTo = cm.doc.first; + cm.display.view = []; + cm.display.viewOffset = 0; + } + + function viewCuttingPoint(cm, oldN, newN, dir) { + var index = findViewIndex(cm, oldN), diff, view = cm.display.view; + if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) + { return {index: index, lineN: newN} } + var n = cm.display.viewFrom; + for (var i = 0; i < index; i++) + { n += view[i].size; } + if (n != oldN) { + if (dir > 0) { + if (index == view.length - 1) { return null } + diff = (n + view[index].size) - oldN; + index++; + } else { + diff = n - oldN; + } + oldN += diff; newN += diff; + } + while (visualLineNo(cm.doc, newN) != newN) { + if (index == (dir < 0 ? 0 : view.length - 1)) { return null } + newN += dir * view[index - (dir < 0 ? 1 : 0)].size; + index += dir; + } + return {index: index, lineN: newN} + } + + // Force the view to cover a given range, adding empty view element + // or clipping off existing ones as needed. + function adjustView(cm, from, to) { + var display = cm.display, view = display.view; + if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { + display.view = buildViewArray(cm, from, to); + display.viewFrom = from; + } else { + if (display.viewFrom > from) + { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); } + else if (display.viewFrom < from) + { display.view = display.view.slice(findViewIndex(cm, from)); } + display.viewFrom = from; + if (display.viewTo < to) + { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); } + else if (display.viewTo > to) + { display.view = display.view.slice(0, findViewIndex(cm, to)); } + } + display.viewTo = to; + } + + // Count the number of lines in the view whose DOM representation is + // out of date (or nonexistent). + function countDirtyView(cm) { + var view = cm.display.view, dirty = 0; + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; } + } + return dirty + } + + function updateSelection(cm) { + cm.display.input.showSelection(cm.display.input.prepareSelection()); + } + + function prepareSelection(cm, primary) { + if ( primary === void 0 ) primary = true; + + var doc = cm.doc, result = {}; + var curFragment = result.cursors = document.createDocumentFragment(); + var selFragment = result.selection = document.createDocumentFragment(); + + for (var i = 0; i < doc.sel.ranges.length; i++) { + if (!primary && i == doc.sel.primIndex) { continue } + var range$$1 = doc.sel.ranges[i]; + if (range$$1.from().line >= cm.display.viewTo || range$$1.to().line < cm.display.viewFrom) { continue } + var collapsed = range$$1.empty(); + if (collapsed || cm.options.showCursorWhenSelecting) + { drawSelectionCursor(cm, range$$1.head, curFragment); } + if (!collapsed) + { drawSelectionRange(cm, range$$1, selFragment); } + } + return result + } + + // Draws a cursor for the given range + function drawSelectionCursor(cm, head, output) { + var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); + + var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); + cursor.style.left = pos.left + "px"; + cursor.style.top = pos.top + "px"; + cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; + + if (pos.other) { + // Secondary cursor, shown when on a 'jump' in bi-directional text + var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); + otherCursor.style.display = ""; + otherCursor.style.left = pos.other.left + "px"; + otherCursor.style.top = pos.other.top + "px"; + otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; + } + } + + function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } + + // Draws the given range as a highlighted selection + function drawSelectionRange(cm, range$$1, output) { + var display = cm.display, doc = cm.doc; + var fragment = document.createDocumentFragment(); + var padding = paddingH(cm.display), leftSide = padding.left; + var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; + var docLTR = doc.direction == "ltr"; + + function add(left, top, width, bottom) { + if (top < 0) { top = 0; } + top = Math.round(top); + bottom = Math.round(bottom); + fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))); + } + + function drawForLine(line, fromArg, toArg) { + var lineObj = getLine(doc, line); + var lineLen = lineObj.text.length; + var start, end; + function coords(ch, bias) { + return charCoords(cm, Pos(line, ch), "div", lineObj, bias) + } + + function wrapX(pos, dir, side) { + var extent = wrappedLineExtentChar(cm, lineObj, null, pos); + var prop = (dir == "ltr") == (side == "after") ? "left" : "right"; + var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1); + return coords(ch, prop)[prop] + } + + var order = getOrder(lineObj, doc.direction); + iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { + var ltr = dir == "ltr"; + var fromPos = coords(from, ltr ? "left" : "right"); + var toPos = coords(to - 1, ltr ? "right" : "left"); + + var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen; + var first = i == 0, last = !order || i == order.length - 1; + if (toPos.top - fromPos.top <= 3) { // Single line + var openLeft = (docLTR ? openStart : openEnd) && first; + var openRight = (docLTR ? openEnd : openStart) && last; + var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left; + var right = openRight ? rightSide : (ltr ? toPos : fromPos).right; + add(left, fromPos.top, right - left, fromPos.bottom); + } else { // Multiple lines + var topLeft, topRight, botLeft, botRight; + if (ltr) { + topLeft = docLTR && openStart && first ? leftSide : fromPos.left; + topRight = docLTR ? rightSide : wrapX(from, dir, "before"); + botLeft = docLTR ? leftSide : wrapX(to, dir, "after"); + botRight = docLTR && openEnd && last ? rightSide : toPos.right; + } else { + topLeft = !docLTR ? leftSide : wrapX(from, dir, "before"); + topRight = !docLTR && openStart && first ? rightSide : fromPos.right; + botLeft = !docLTR && openEnd && last ? leftSide : toPos.left; + botRight = !docLTR ? rightSide : wrapX(to, dir, "after"); + } + add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom); + if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); } + add(botLeft, toPos.top, botRight - botLeft, toPos.bottom); + } + + if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; } + if (cmpCoords(toPos, start) < 0) { start = toPos; } + if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; } + if (cmpCoords(toPos, end) < 0) { end = toPos; } + }); + return {start: start, end: end} + } + + var sFrom = range$$1.from(), sTo = range$$1.to(); + if (sFrom.line == sTo.line) { + drawForLine(sFrom.line, sFrom.ch, sTo.ch); + } else { + var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); + var singleVLine = visualLine(fromLine) == visualLine(toLine); + var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; + var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; + if (singleVLine) { + if (leftEnd.top < rightStart.top - 2) { + add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); + add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); + } else { + add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); + } + } + if (leftEnd.bottom < rightStart.top) + { add(leftSide, leftEnd.bottom, null, rightStart.top); } + } + + output.appendChild(fragment); + } + + // Cursor-blinking + function restartBlink(cm) { + if (!cm.state.focused) { return } + var display = cm.display; + clearInterval(display.blinker); + var on = true; + display.cursorDiv.style.visibility = ""; + if (cm.options.cursorBlinkRate > 0) + { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; }, + cm.options.cursorBlinkRate); } + else if (cm.options.cursorBlinkRate < 0) + { display.cursorDiv.style.visibility = "hidden"; } + } + + function ensureFocus(cm) { + if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); } + } + + function delayBlurEvent(cm) { + cm.state.delayingBlurEvent = true; + setTimeout(function () { if (cm.state.delayingBlurEvent) { + cm.state.delayingBlurEvent = false; + onBlur(cm); + } }, 100); + } + + function onFocus(cm, e) { + if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; } + + if (cm.options.readOnly == "nocursor") { return } + if (!cm.state.focused) { + signal(cm, "focus", cm, e); + cm.state.focused = true; + addClass(cm.display.wrapper, "CodeMirror-focused"); + // This test prevents this from firing when a context + // menu is closed (since the input reset would kill the + // select-all detection hack) + if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { + cm.display.input.reset(); + if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730 + } + cm.display.input.receivedFocus(); + } + restartBlink(cm); + } + function onBlur(cm, e) { + if (cm.state.delayingBlurEvent) { return } + + if (cm.state.focused) { + signal(cm, "blur", cm, e); + cm.state.focused = false; + rmClass(cm.display.wrapper, "CodeMirror-focused"); + } + clearInterval(cm.display.blinker); + setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150); + } + + // Read the actual heights of the rendered lines, and update their + // stored heights to match. + function updateHeightsInViewport(cm) { + var display = cm.display; + var prevBottom = display.lineDiv.offsetTop; + for (var i = 0; i < display.view.length; i++) { + var cur = display.view[i], wrapping = cm.options.lineWrapping; + var height = (void 0), width = 0; + if (cur.hidden) { continue } + if (ie && ie_version < 8) { + var bot = cur.node.offsetTop + cur.node.offsetHeight; + height = bot - prevBottom; + prevBottom = bot; + } else { + var box = cur.node.getBoundingClientRect(); + height = box.bottom - box.top; + // Check that lines don't extend past the right of the current + // editor width + if (!wrapping && cur.text.firstChild) + { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; } + } + var diff = cur.line.height - height; + if (diff > .005 || diff < -.005) { + updateLineHeight(cur.line, height); + updateWidgetHeight(cur.line); + if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) + { updateWidgetHeight(cur.rest[j]); } } + } + if (width > cm.display.sizerWidth) { + var chWidth = Math.ceil(width / charWidth(cm.display)); + if (chWidth > cm.display.maxLineLength) { + cm.display.maxLineLength = chWidth; + cm.display.maxLine = cur.line; + cm.display.maxLineChanged = true; + } + } + } + } + + // Read and store the height of line widgets associated with the + // given line. + function updateWidgetHeight(line) { + if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) { + var w = line.widgets[i], parent = w.node.parentNode; + if (parent) { w.height = parent.offsetHeight; } + } } + } + + // Compute the lines that are visible in a given viewport (defaults + // the the current scroll position). viewport may contain top, + // height, and ensure (see op.scrollToPos) properties. + function visibleLines(display, doc, viewport) { + var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; + top = Math.floor(top - paddingTop(display)); + var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; + + var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); + // Ensure is a {from: {line, ch}, to: {line, ch}} object, and + // forces those lines into the viewport (if possible). + if (viewport && viewport.ensure) { + var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; + if (ensureFrom < from) { + from = ensureFrom; + to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); + } else if (Math.min(ensureTo, doc.lastLine()) >= to) { + from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); + to = ensureTo; + } + } + return {from: from, to: Math.max(to, from + 1)} + } + + // SCROLLING THINGS INTO VIEW + + // If an editor sits on the top or bottom of the window, partially + // scrolled out of view, this ensures that the cursor is visible. + function maybeScrollWindow(cm, rect) { + if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } + + var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; + if (rect.top + box.top < 0) { doScroll = true; } + else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; } + if (doScroll != null && !phantom) { + var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;")); + cm.display.lineSpace.appendChild(scrollNode); + scrollNode.scrollIntoView(doScroll); + cm.display.lineSpace.removeChild(scrollNode); + } + } + + // Scroll a given position into view (immediately), verifying that + // it actually became visible (as line heights are accurately + // measured, the position of something may 'drift' during drawing). + function scrollPosIntoView(cm, pos, end, margin) { + if (margin == null) { margin = 0; } + var rect; + if (!cm.options.lineWrapping && pos == end) { + // Set pos and end to the cursor positions around the character pos sticks to + // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch + // If pos == Pos(_, 0, "before"), pos and end are unchanged + pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos; + end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos; + } + for (var limit = 0; limit < 5; limit++) { + var changed = false; + var coords = cursorCoords(cm, pos); + var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); + rect = {left: Math.min(coords.left, endCoords.left), + top: Math.min(coords.top, endCoords.top) - margin, + right: Math.max(coords.left, endCoords.left), + bottom: Math.max(coords.bottom, endCoords.bottom) + margin}; + var scrollPos = calculateScrollPos(cm, rect); + var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; + if (scrollPos.scrollTop != null) { + updateScrollTop(cm, scrollPos.scrollTop); + if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; } + } + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; } + } + if (!changed) { break } + } + return rect + } + + // Scroll a given set of coordinates into view (immediately). + function scrollIntoView(cm, rect) { + var scrollPos = calculateScrollPos(cm, rect); + if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); } + if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); } + } + + // Calculate a new scroll position needed to scroll the given + // rectangle into view. Returns an object with scrollTop and + // scrollLeft properties. When these are undefined, the + // vertical/horizontal position does not need to be adjusted. + function calculateScrollPos(cm, rect) { + var display = cm.display, snapMargin = textHeight(cm.display); + if (rect.top < 0) { rect.top = 0; } + var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; + var screen = displayHeight(cm), result = {}; + if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; } + var docBottom = cm.doc.height + paddingVert(display); + var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin; + if (rect.top < screentop) { + result.scrollTop = atTop ? 0 : rect.top; + } else if (rect.bottom > screentop + screen) { + var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen); + if (newTop != screentop) { result.scrollTop = newTop; } + } + + var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; + var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0); + var tooWide = rect.right - rect.left > screenw; + if (tooWide) { rect.right = rect.left + screenw; } + if (rect.left < 10) + { result.scrollLeft = 0; } + else if (rect.left < screenleft) + { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); } + else if (rect.right > screenw + screenleft - 3) + { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; } + return result + } + + // Store a relative adjustment to the scroll position in the current + // operation (to be applied when the operation finishes). + function addToScrollTop(cm, top) { + if (top == null) { return } + resolveScrollToPos(cm); + cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; + } + + // Make sure that at the end of the operation the current cursor is + // shown. + function ensureCursorVisible(cm) { + resolveScrollToPos(cm); + var cur = cm.getCursor(); + cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin}; + } + + function scrollToCoords(cm, x, y) { + if (x != null || y != null) { resolveScrollToPos(cm); } + if (x != null) { cm.curOp.scrollLeft = x; } + if (y != null) { cm.curOp.scrollTop = y; } + } + + function scrollToRange(cm, range$$1) { + resolveScrollToPos(cm); + cm.curOp.scrollToPos = range$$1; + } + + // When an operation has its scrollToPos property set, and another + // scroll action is applied before the end of the operation, this + // 'simulates' scrolling that position into view in a cheap way, so + // that the effect of intermediate scroll commands is not ignored. + function resolveScrollToPos(cm) { + var range$$1 = cm.curOp.scrollToPos; + if (range$$1) { + cm.curOp.scrollToPos = null; + var from = estimateCoords(cm, range$$1.from), to = estimateCoords(cm, range$$1.to); + scrollToCoordsRange(cm, from, to, range$$1.margin); + } + } + + function scrollToCoordsRange(cm, from, to, margin) { + var sPos = calculateScrollPos(cm, { + left: Math.min(from.left, to.left), + top: Math.min(from.top, to.top) - margin, + right: Math.max(from.right, to.right), + bottom: Math.max(from.bottom, to.bottom) + margin + }); + scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop); + } + + // Sync the scrollable area and scrollbars, ensure the viewport + // covers the visible area. + function updateScrollTop(cm, val) { + if (Math.abs(cm.doc.scrollTop - val) < 2) { return } + if (!gecko) { updateDisplaySimple(cm, {top: val}); } + setScrollTop(cm, val, true); + if (gecko) { updateDisplaySimple(cm); } + startWorker(cm, 100); + } + + function setScrollTop(cm, val, forceScroll) { + val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val); + if (cm.display.scroller.scrollTop == val && !forceScroll) { return } + cm.doc.scrollTop = val; + cm.display.scrollbars.setScrollTop(val); + if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; } + } + + // Sync scroller and scrollbar, ensure the gutter elements are + // aligned. + function setScrollLeft(cm, val, isScroller, forceScroll) { + val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); + if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return } + cm.doc.scrollLeft = val; + alignHorizontally(cm); + if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; } + cm.display.scrollbars.setScrollLeft(val); + } + + // SCROLLBARS + + // Prepare DOM reads needed to update the scrollbars. Done in one + // shot to minimize update/measure roundtrips. + function measureForScrollbars(cm) { + var d = cm.display, gutterW = d.gutters.offsetWidth; + var docH = Math.round(cm.doc.height + paddingVert(cm.display)); + return { + clientHeight: d.scroller.clientHeight, + viewHeight: d.wrapper.clientHeight, + scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, + viewWidth: d.wrapper.clientWidth, + barLeft: cm.options.fixedGutter ? gutterW : 0, + docHeight: docH, + scrollHeight: docH + scrollGap(cm) + d.barHeight, + nativeBarWidth: d.nativeBarWidth, + gutterWidth: gutterW + } + } + + var NativeScrollbars = function(place, scroll, cm) { + this.cm = cm; + var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); + var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); + vert.tabIndex = horiz.tabIndex = -1; + place(vert); place(horiz); + + on(vert, "scroll", function () { + if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); } + }); + on(horiz, "scroll", function () { + if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); } + }); + + this.checkedZeroWidth = false; + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; } + }; + + NativeScrollbars.prototype.update = function (measure) { + var needsH = measure.scrollWidth > measure.clientWidth + 1; + var needsV = measure.scrollHeight > measure.clientHeight + 1; + var sWidth = measure.nativeBarWidth; + + if (needsV) { + this.vert.style.display = "block"; + this.vert.style.bottom = needsH ? sWidth + "px" : "0"; + var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); + // A bug in IE8 can cause this value to be negative, so guard it. + this.vert.firstChild.style.height = + Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; + } else { + this.vert.style.display = ""; + this.vert.firstChild.style.height = "0"; + } + + if (needsH) { + this.horiz.style.display = "block"; + this.horiz.style.right = needsV ? sWidth + "px" : "0"; + this.horiz.style.left = measure.barLeft + "px"; + var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); + this.horiz.firstChild.style.width = + Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; + } else { + this.horiz.style.display = ""; + this.horiz.firstChild.style.width = "0"; + } + + if (!this.checkedZeroWidth && measure.clientHeight > 0) { + if (sWidth == 0) { this.zeroWidthHack(); } + this.checkedZeroWidth = true; + } + + return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} + }; + + NativeScrollbars.prototype.setScrollLeft = function (pos) { + if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; } + if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); } + }; + + NativeScrollbars.prototype.setScrollTop = function (pos) { + if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; } + if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); } + }; + + NativeScrollbars.prototype.zeroWidthHack = function () { + var w = mac && !mac_geMountainLion ? "12px" : "18px"; + this.horiz.style.height = this.vert.style.width = w; + this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"; + this.disableHoriz = new Delayed; + this.disableVert = new Delayed; + }; + + NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) { + bar.style.pointerEvents = "auto"; + function maybeDisable() { + // To find out whether the scrollbar is still visible, we + // check whether the element under the pixel in the bottom + // right corner of the scrollbar box is the scrollbar box + // itself (when the bar is still visible) or its filler child + // (when the bar is hidden). If it is still visible, we keep + // it enabled, if it's hidden, we disable pointer events. + var box = bar.getBoundingClientRect(); + var elt$$1 = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2) + : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1); + if (elt$$1 != bar) { bar.style.pointerEvents = "none"; } + else { delay.set(1000, maybeDisable); } + } + delay.set(1000, maybeDisable); + }; + + NativeScrollbars.prototype.clear = function () { + var parent = this.horiz.parentNode; + parent.removeChild(this.horiz); + parent.removeChild(this.vert); + }; + + var NullScrollbars = function () {}; + + NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; + NullScrollbars.prototype.setScrollLeft = function () {}; + NullScrollbars.prototype.setScrollTop = function () {}; + NullScrollbars.prototype.clear = function () {}; + + function updateScrollbars(cm, measure) { + if (!measure) { measure = measureForScrollbars(cm); } + var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; + updateScrollbarsInner(cm, measure); + for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { + if (startWidth != cm.display.barWidth && cm.options.lineWrapping) + { updateHeightsInViewport(cm); } + updateScrollbarsInner(cm, measureForScrollbars(cm)); + startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; + } + } + + // Re-synchronize the fake scrollbars with the actual size of the + // content. + function updateScrollbarsInner(cm, measure) { + var d = cm.display; + var sizes = d.scrollbars.update(measure); + + d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; + d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; + d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"; + + if (sizes.right && sizes.bottom) { + d.scrollbarFiller.style.display = "block"; + d.scrollbarFiller.style.height = sizes.bottom + "px"; + d.scrollbarFiller.style.width = sizes.right + "px"; + } else { d.scrollbarFiller.style.display = ""; } + if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { + d.gutterFiller.style.display = "block"; + d.gutterFiller.style.height = sizes.bottom + "px"; + d.gutterFiller.style.width = measure.gutterWidth + "px"; + } else { d.gutterFiller.style.display = ""; } + } + + var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; + + function initScrollbars(cm) { + if (cm.display.scrollbars) { + cm.display.scrollbars.clear(); + if (cm.display.scrollbars.addClass) + { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); } + } + + cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { + cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); + // Prevent clicks in the scrollbars from killing focus + on(node, "mousedown", function () { + if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); } + }); + node.setAttribute("cm-not-content", "true"); + }, function (pos, axis) { + if (axis == "horizontal") { setScrollLeft(cm, pos); } + else { updateScrollTop(cm, pos); } + }, cm); + if (cm.display.scrollbars.addClass) + { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); } + } + + // Operations are used to wrap a series of changes to the editor + // state in such a way that each change won't have to update the + // cursor and display (which would be awkward, slow, and + // error-prone). Instead, display updates are batched and then all + // combined and executed at once. + + var nextOpId = 0; + // Start a new operation. + function startOperation(cm) { + cm.curOp = { + cm: cm, + viewChanged: false, // Flag that indicates that lines might need to be redrawn + startHeight: cm.doc.height, // Used to detect need to update scrollbar + forceUpdate: false, // Used to force a redraw + updateInput: 0, // Whether to reset the input textarea + typing: false, // Whether this reset should be careful to leave existing text (for compositing) + changeObjs: null, // Accumulated changes, for firing change events + cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on + cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already + selectionChanged: false, // Whether the selection needs to be redrawn + updateMaxLine: false, // Set when the widest line needs to be determined anew + scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet + scrollToPos: null, // Used to scroll to a specific position + focus: false, + id: ++nextOpId // Unique ID + }; + pushOperation(cm.curOp); + } + + // Finish an operation, updating the display and signalling delayed events + function endOperation(cm) { + var op = cm.curOp; + if (op) { finishOperation(op, function (group) { + for (var i = 0; i < group.ops.length; i++) + { group.ops[i].cm.curOp = null; } + endOperations(group); + }); } + } + + // The DOM updates done when an operation finishes are batched so + // that the minimum number of relayouts are required. + function endOperations(group) { + var ops = group.ops; + for (var i = 0; i < ops.length; i++) // Read DOM + { endOperation_R1(ops[i]); } + for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) + { endOperation_W1(ops[i$1]); } + for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM + { endOperation_R2(ops[i$2]); } + for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) + { endOperation_W2(ops[i$3]); } + for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM + { endOperation_finish(ops[i$4]); } + } + + function endOperation_R1(op) { + var cm = op.cm, display = cm.display; + maybeClipScrollbars(cm); + if (op.updateMaxLine) { findMaxLine(cm); } + + op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || + op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || + op.scrollToPos.to.line >= display.viewTo) || + display.maxLineChanged && cm.options.lineWrapping; + op.update = op.mustUpdate && + new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); + } + + function endOperation_W1(op) { + op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); + } + + function endOperation_R2(op) { + var cm = op.cm, display = cm.display; + if (op.updatedDisplay) { updateHeightsInViewport(cm); } + + op.barMeasure = measureForScrollbars(cm); + + // If the max line changed since it was last measured, measure it, + // and ensure the document's width matches it. + // updateDisplay_W2 will use these properties to do the actual resizing + if (display.maxLineChanged && !cm.options.lineWrapping) { + op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; + cm.display.sizerWidth = op.adjustWidthTo; + op.barMeasure.scrollWidth = + Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); + op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); + } + + if (op.updatedDisplay || op.selectionChanged) + { op.preparedSelection = display.input.prepareSelection(); } + } + + function endOperation_W2(op) { + var cm = op.cm; + + if (op.adjustWidthTo != null) { + cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; + if (op.maxScrollLeft < cm.doc.scrollLeft) + { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); } + cm.display.maxLineChanged = false; + } + + var takeFocus = op.focus && op.focus == activeElt(); + if (op.preparedSelection) + { cm.display.input.showSelection(op.preparedSelection, takeFocus); } + if (op.updatedDisplay || op.startHeight != cm.doc.height) + { updateScrollbars(cm, op.barMeasure); } + if (op.updatedDisplay) + { setDocumentHeight(cm, op.barMeasure); } + + if (op.selectionChanged) { restartBlink(cm); } + + if (cm.state.focused && op.updateInput) + { cm.display.input.reset(op.typing); } + if (takeFocus) { ensureFocus(op.cm); } + } + + function endOperation_finish(op) { + var cm = op.cm, display = cm.display, doc = cm.doc; + + if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); } + + // Abort mouse wheel delta measurement, when scrolling explicitly + if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) + { display.wheelStartX = display.wheelStartY = null; } + + // Propagate the scroll position to the actual DOM scroller + if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); } + + if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); } + // If we need to scroll a specific position into view, do so. + if (op.scrollToPos) { + var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), + clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); + maybeScrollWindow(cm, rect); + } + + // Fire events for markers that are hidden/unidden by editing or + // undoing + var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; + if (hidden) { for (var i = 0; i < hidden.length; ++i) + { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } } + if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) + { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } } + + if (display.wrapper.offsetHeight) + { doc.scrollTop = cm.display.scroller.scrollTop; } + + // Fire change events, and delayed event handlers + if (op.changeObjs) + { signal(cm, "changes", cm, op.changeObjs); } + if (op.update) + { op.update.finish(); } + } + + // Run the given function in an operation + function runInOp(cm, f) { + if (cm.curOp) { return f() } + startOperation(cm); + try { return f() } + finally { endOperation(cm); } + } + // Wraps a function in an operation. Returns the wrapped function. + function operation(cm, f) { + return function() { + if (cm.curOp) { return f.apply(cm, arguments) } + startOperation(cm); + try { return f.apply(cm, arguments) } + finally { endOperation(cm); } + } + } + // Used to add methods to editor and doc instances, wrapping them in + // operations. + function methodOp(f) { + return function() { + if (this.curOp) { return f.apply(this, arguments) } + startOperation(this); + try { return f.apply(this, arguments) } + finally { endOperation(this); } + } + } + function docMethodOp(f) { + return function() { + var cm = this.cm; + if (!cm || cm.curOp) { return f.apply(this, arguments) } + startOperation(cm); + try { return f.apply(this, arguments) } + finally { endOperation(cm); } + } + } + + // HIGHLIGHT WORKER + + function startWorker(cm, time) { + if (cm.doc.highlightFrontier < cm.display.viewTo) + { cm.state.highlight.set(time, bind(highlightWorker, cm)); } + } + + function highlightWorker(cm) { + var doc = cm.doc; + if (doc.highlightFrontier >= cm.display.viewTo) { return } + var end = +new Date + cm.options.workTime; + var context = getContextBefore(cm, doc.highlightFrontier); + var changedLines = []; + + doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { + if (context.line >= cm.display.viewFrom) { // Visible + var oldStyles = line.styles; + var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null; + var highlighted = highlightLine(cm, line, context, true); + if (resetState) { context.state = resetState; } + line.styles = highlighted.styles; + var oldCls = line.styleClasses, newCls = highlighted.classes; + if (newCls) { line.styleClasses = newCls; } + else if (oldCls) { line.styleClasses = null; } + var ischange = !oldStyles || oldStyles.length != line.styles.length || + oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); + for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; } + if (ischange) { changedLines.push(context.line); } + line.stateAfter = context.save(); + context.nextLine(); + } else { + if (line.text.length <= cm.options.maxHighlightLength) + { processLine(cm, line.text, context); } + line.stateAfter = context.line % 5 == 0 ? context.save() : null; + context.nextLine(); + } + if (+new Date > end) { + startWorker(cm, cm.options.workDelay); + return true + } + }); + doc.highlightFrontier = context.line; + doc.modeFrontier = Math.max(doc.modeFrontier, context.line); + if (changedLines.length) { runInOp(cm, function () { + for (var i = 0; i < changedLines.length; i++) + { regLineChange(cm, changedLines[i], "text"); } + }); } + } + + // DISPLAY DRAWING + + var DisplayUpdate = function(cm, viewport, force) { + var display = cm.display; + + this.viewport = viewport; + // Store some values that we'll need later (but don't want to force a relayout for) + this.visible = visibleLines(display, cm.doc, viewport); + this.editorIsHidden = !display.wrapper.offsetWidth; + this.wrapperHeight = display.wrapper.clientHeight; + this.wrapperWidth = display.wrapper.clientWidth; + this.oldDisplayWidth = displayWidth(cm); + this.force = force; + this.dims = getDimensions(cm); + this.events = []; + }; + + DisplayUpdate.prototype.signal = function (emitter, type) { + if (hasHandler(emitter, type)) + { this.events.push(arguments); } + }; + DisplayUpdate.prototype.finish = function () { + var this$1 = this; + + for (var i = 0; i < this.events.length; i++) + { signal.apply(null, this$1.events[i]); } + }; + + function maybeClipScrollbars(cm) { + var display = cm.display; + if (!display.scrollbarsClipped && display.scroller.offsetWidth) { + display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; + display.heightForcer.style.height = scrollGap(cm) + "px"; + display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; + display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; + display.scrollbarsClipped = true; + } + } + + function selectionSnapshot(cm) { + if (cm.hasFocus()) { return null } + var active = activeElt(); + if (!active || !contains(cm.display.lineDiv, active)) { return null } + var result = {activeElt: active}; + if (window.getSelection) { + var sel = window.getSelection(); + if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { + result.anchorNode = sel.anchorNode; + result.anchorOffset = sel.anchorOffset; + result.focusNode = sel.focusNode; + result.focusOffset = sel.focusOffset; + } + } + return result + } + + function restoreSelection(snapshot) { + if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return } + snapshot.activeElt.focus(); + if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { + var sel = window.getSelection(), range$$1 = document.createRange(); + range$$1.setEnd(snapshot.anchorNode, snapshot.anchorOffset); + range$$1.collapse(false); + sel.removeAllRanges(); + sel.addRange(range$$1); + sel.extend(snapshot.focusNode, snapshot.focusOffset); + } + } + + // Does the actual updating of the line display. Bails out + // (returning false) when there is nothing to be done and forced is + // false. + function updateDisplayIfNeeded(cm, update) { + var display = cm.display, doc = cm.doc; + + if (update.editorIsHidden) { + resetView(cm); + return false + } + + // Bail out if the visible area is already rendered and nothing changed. + if (!update.force && + update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && + display.renderedView == display.view && countDirtyView(cm) == 0) + { return false } + + if (maybeUpdateLineNumberWidth(cm)) { + resetView(cm); + update.dims = getDimensions(cm); + } + + // Compute a suitable new viewport (from & to) + var end = doc.first + doc.size; + var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); + var to = Math.min(end, update.visible.to + cm.options.viewportMargin); + if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); } + if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); } + if (sawCollapsedSpans) { + from = visualLineNo(cm.doc, from); + to = visualLineEndNo(cm.doc, to); + } + + var different = from != display.viewFrom || to != display.viewTo || + display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; + adjustView(cm, from, to); + + display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); + // Position the mover div to align with the current scroll position + cm.display.mover.style.top = display.viewOffset + "px"; + + var toUpdate = countDirtyView(cm); + if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) + { return false } + + // For big changes, we hide the enclosing element during the + // update, since that speeds up the operations on most browsers. + var selSnapshot = selectionSnapshot(cm); + if (toUpdate > 4) { display.lineDiv.style.display = "none"; } + patchDisplay(cm, display.updateLineNumbers, update.dims); + if (toUpdate > 4) { display.lineDiv.style.display = ""; } + display.renderedView = display.view; + // There might have been a widget with a focused element that got + // hidden or updated, if so re-focus it. + restoreSelection(selSnapshot); + + // Prevent selection and cursors from interfering with the scroll + // width and height. + removeChildren(display.cursorDiv); + removeChildren(display.selectionDiv); + display.gutters.style.height = display.sizer.style.minHeight = 0; + + if (different) { + display.lastWrapHeight = update.wrapperHeight; + display.lastWrapWidth = update.wrapperWidth; + startWorker(cm, 400); + } + + display.updateLineNumbers = null; + + return true + } + + function postUpdateDisplay(cm, update) { + var viewport = update.viewport; + + for (var first = true;; first = false) { + if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { + // Clip forced viewport to actual scrollable area. + if (viewport && viewport.top != null) + { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; } + // Updated line heights might result in the drawn area not + // actually covering the viewport. Keep looping until it does. + update.visible = visibleLines(cm.display, cm.doc, viewport); + if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) + { break } + } + if (!updateDisplayIfNeeded(cm, update)) { break } + updateHeightsInViewport(cm); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.force = false; + } + + update.signal(cm, "update", cm); + if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { + update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); + cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; + } + } + + function updateDisplaySimple(cm, viewport) { + var update = new DisplayUpdate(cm, viewport); + if (updateDisplayIfNeeded(cm, update)) { + updateHeightsInViewport(cm); + postUpdateDisplay(cm, update); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.finish(); + } + } + + // Sync the actual display DOM structure with display.view, removing + // nodes for lines that are no longer in view, and creating the ones + // that are not there yet, and updating the ones that are out of + // date. + function patchDisplay(cm, updateNumbersFrom, dims) { + var display = cm.display, lineNumbers = cm.options.lineNumbers; + var container = display.lineDiv, cur = container.firstChild; + + function rm(node) { + var next = node.nextSibling; + // Works around a throw-scroll bug in OS X Webkit + if (webkit && mac && cm.display.currentWheelTarget == node) + { node.style.display = "none"; } + else + { node.parentNode.removeChild(node); } + return next + } + + var view = display.view, lineN = display.viewFrom; + // Loop over the elements in the view, syncing cur (the DOM nodes + // in display.lineDiv) with the view as we go. + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet + var node = buildLineElement(cm, lineView, lineN, dims); + container.insertBefore(node, cur); + } else { // Already drawn + while (cur != lineView.node) { cur = rm(cur); } + var updateNumber = lineNumbers && updateNumbersFrom != null && + updateNumbersFrom <= lineN && lineView.lineNumber; + if (lineView.changes) { + if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; } + updateLineForChanges(cm, lineView, lineN, dims); + } + if (updateNumber) { + removeChildren(lineView.lineNumber); + lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); + } + cur = lineView.node.nextSibling; + } + lineN += lineView.size; + } + while (cur) { cur = rm(cur); } + } + + function updateGutterSpace(display) { + var width = display.gutters.offsetWidth; + display.sizer.style.marginLeft = width + "px"; + } + + function setDocumentHeight(cm, measure) { + cm.display.sizer.style.minHeight = measure.docHeight + "px"; + cm.display.heightForcer.style.top = measure.docHeight + "px"; + cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; + } + + // Re-align line numbers and gutter marks to compensate for + // horizontal scrolling. + function alignHorizontally(cm) { + var display = cm.display, view = display.view; + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; + var gutterW = display.gutters.offsetWidth, left = comp + "px"; + for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { + if (cm.options.fixedGutter) { + if (view[i].gutter) + { view[i].gutter.style.left = left; } + if (view[i].gutterBackground) + { view[i].gutterBackground.style.left = left; } + } + var align = view[i].alignable; + if (align) { for (var j = 0; j < align.length; j++) + { align[j].style.left = left; } } + } } + if (cm.options.fixedGutter) + { display.gutters.style.left = (comp + gutterW) + "px"; } + } + + // Used to ensure that the line number gutter is still the right + // size for the current document size. Returns true when an update + // is needed. + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) { return false } + var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + updateGutterSpace(cm.display); + return true + } + return false + } + + function getGutters(gutters, lineNumbers) { + var result = [], sawLineNumbers = false; + for (var i = 0; i < gutters.length; i++) { + var name = gutters[i], style = null; + if (typeof name != "string") { style = name.style; name = name.className; } + if (name == "CodeMirror-linenumbers") { + if (!lineNumbers) { continue } + else { sawLineNumbers = true; } + } + result.push({className: name, style: style}); + } + if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); } + return result + } + + // Rebuild the gutter elements, ensure the margin to the left of the + // code matches their width. + function renderGutters(display) { + var gutters = display.gutters, specs = display.gutterSpecs; + removeChildren(gutters); + display.lineGutter = null; + for (var i = 0; i < specs.length; ++i) { + var ref = specs[i]; + var className = ref.className; + var style = ref.style; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className)); + if (style) { gElt.style.cssText = style; } + if (className == "CodeMirror-linenumbers") { + display.lineGutter = gElt; + gElt.style.width = (display.lineNumWidth || 1) + "px"; + } + } + gutters.style.display = specs.length ? "" : "none"; + updateGutterSpace(display); + } + + function updateGutters(cm) { + renderGutters(cm.display); + regChange(cm); + alignHorizontally(cm); + } + + // The display handles the DOM integration, both for input reading + // and content drawing. It holds references to DOM nodes and + // display-related state. + + function Display(place, doc, input, options) { + var d = this; + this.input = input; + + // Covers bottom-right square when both scrollbars are present. + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + d.scrollbarFiller.setAttribute("cm-not-content", "true"); + // Covers bottom of gutter when coverGutterNextToScrollbar is on + // and h scrollbar is present. + d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); + d.gutterFiller.setAttribute("cm-not-content", "true"); + // Will contain the actual code, positioned to cover the viewport. + d.lineDiv = eltP("div", null, "CodeMirror-code"); + // Elements are added to these to represent selection and cursors. + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + d.cursorDiv = elt("div", null, "CodeMirror-cursors"); + // A visibility: hidden element used to find the size of things. + d.measure = elt("div", null, "CodeMirror-measure"); + // When lines outside of the viewport are measured, they are drawn in this. + d.lineMeasure = elt("div", null, "CodeMirror-measure"); + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], + null, "position: relative; outline: none"); + var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); + // Moved around its parent to cover visible view. + d.mover = elt("div", [lines], null, "position: relative"); + // Set to the height of the document, allowing scrolling. + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + d.sizerWidth = null; + // Behavior of elts with overflow: auto and padding is + // inconsistent across browsers. This is used to ensure the + // scrollable area is big enough. + d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); + // Will contain the gutters, if any. + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; + // Actual scrollable element. + d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); + d.scroller.setAttribute("tabIndex", "-1"); + // The element in which the editor lives. + d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); + + // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) + if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } + if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; } + + if (place) { + if (place.appendChild) { place.appendChild(d.wrapper); } + else { place(d.wrapper); } + } + + // Current rendered range (may be bigger than the view window). + d.viewFrom = d.viewTo = doc.first; + d.reportedViewFrom = d.reportedViewTo = doc.first; + // Information about the rendered lines. + d.view = []; + d.renderedView = null; + // Holds info about a single rendered line when it was rendered + // for measurement, while not in view. + d.externalMeasured = null; + // Empty space (in pixels) above the view + d.viewOffset = 0; + d.lastWrapHeight = d.lastWrapWidth = 0; + d.updateLineNumbers = null; + + d.nativeBarWidth = d.barHeight = d.barWidth = 0; + d.scrollbarsClipped = false; + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; + // Set to true when a non-horizontal-scrolling line widget is + // added. As an optimization, line widget aligning is skipped when + // this is false. + d.alignWidgets = false; + + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + d.maxLine = null; + d.maxLineLength = 0; + d.maxLineChanged = false; + + // Used for measuring wheel scrolling granularity + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; + + // True when shift is held down. + d.shift = false; + + // Used to track whether anything happened since the context menu + // was opened. + d.selForContextMenu = null; + + d.activeTouch = null; + + d.gutterSpecs = getGutters(options.gutters, options.lineNumbers); + renderGutters(d); + + input.init(d); + } + + // Since the delta values reported on mouse wheel events are + // unstandardized between browsers and even browser versions, and + // generally horribly unpredictable, this code starts by measuring + // the scroll effect that the first few mouse wheel events have, + // and, from that, detects the way it can convert deltas to pixel + // offsets afterwards. + // + // The reason we want to know the amount a wheel event will scroll + // is that it gives us a chance to update the display before the + // actual scrolling happens, reducing flickering. + + var wheelSamples = 0, wheelPixelsPerUnit = null; + // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + if (ie) { wheelPixelsPerUnit = -.53; } + else if (gecko) { wheelPixelsPerUnit = 15; } + else if (chrome) { wheelPixelsPerUnit = -.7; } + else if (safari) { wheelPixelsPerUnit = -1/3; } + + function wheelEventDelta(e) { + var dx = e.wheelDeltaX, dy = e.wheelDeltaY; + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; } + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; } + else if (dy == null) { dy = e.wheelDelta; } + return {x: dx, y: dy} + } + function wheelEventPixels(e) { + var delta = wheelEventDelta(e); + delta.x *= wheelPixelsPerUnit; + delta.y *= wheelPixelsPerUnit; + return delta + } + + function onScrollWheel(cm, e) { + var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; + + var display = cm.display, scroll = display.scroller; + // Quit if there's nothing to scroll here + var canScrollX = scroll.scrollWidth > scroll.clientWidth; + var canScrollY = scroll.scrollHeight > scroll.clientHeight; + if (!(dx && canScrollX || dy && canScrollY)) { return } + + // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + if (dy && mac && webkit) { + outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { + for (var i = 0; i < view.length; i++) { + if (view[i].node == cur) { + cm.display.currentWheelTarget = cur; + break outer + } + } + } + } + + // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { + if (dy && canScrollY) + { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); } + setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit)); + // Only prevent default scrolling if vertical scrolling is + // actually possible. Otherwise, it causes vertical scroll + // jitter on OSX trackpads when deltaX is small and deltaY + // is large (issue #3579) + if (!dy || (dy && canScrollY)) + { e_preventDefault(e); } + display.wheelStartX = null; // Abort measurement, if in progress + return + } + + // 'Project' the visible viewport to cover the area that is being + // scrolled into view (if we know enough to estimate it). + if (dy && wheelPixelsPerUnit != null) { + var pixels = dy * wheelPixelsPerUnit; + var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; + if (pixels < 0) { top = Math.max(0, top + pixels - 50); } + else { bot = Math.min(cm.doc.height, bot + pixels + 50); } + updateDisplaySimple(cm, {top: top, bottom: bot}); + } + + if (wheelSamples < 20) { + if (display.wheelStartX == null) { + display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; + display.wheelDX = dx; display.wheelDY = dy; + setTimeout(function () { + if (display.wheelStartX == null) { return } + var movedX = scroll.scrollLeft - display.wheelStartX; + var movedY = scroll.scrollTop - display.wheelStartY; + var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || + (movedX && display.wheelDX && movedX / display.wheelDX); + display.wheelStartX = display.wheelStartY = null; + if (!sample) { return } + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); + ++wheelSamples; + }, 200); + } else { + display.wheelDX += dx; display.wheelDY += dy; + } + } + } + + // Selection objects are immutable. A new one is created every time + // the selection changes. A selection is one or more non-overlapping + // (and non-touching) ranges, sorted, and an integer that indicates + // which one is the primary selection (the one that's scrolled into + // view, that getCursor returns, etc). + var Selection = function(ranges, primIndex) { + this.ranges = ranges; + this.primIndex = primIndex; + }; + + Selection.prototype.primary = function () { return this.ranges[this.primIndex] }; + + Selection.prototype.equals = function (other) { + var this$1 = this; + + if (other == this) { return true } + if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } + for (var i = 0; i < this.ranges.length; i++) { + var here = this$1.ranges[i], there = other.ranges[i]; + if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false } + } + return true + }; + + Selection.prototype.deepCopy = function () { + var this$1 = this; + + var out = []; + for (var i = 0; i < this.ranges.length; i++) + { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)); } + return new Selection(out, this.primIndex) + }; + + Selection.prototype.somethingSelected = function () { + var this$1 = this; + + for (var i = 0; i < this.ranges.length; i++) + { if (!this$1.ranges[i].empty()) { return true } } + return false + }; + + Selection.prototype.contains = function (pos, end) { + var this$1 = this; + + if (!end) { end = pos; } + for (var i = 0; i < this.ranges.length; i++) { + var range = this$1.ranges[i]; + if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) + { return i } + } + return -1 + }; + + var Range = function(anchor, head) { + this.anchor = anchor; this.head = head; + }; + + Range.prototype.from = function () { return minPos(this.anchor, this.head) }; + Range.prototype.to = function () { return maxPos(this.anchor, this.head) }; + Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }; + + // Take an unsorted, potentially overlapping set of ranges, and + // build a selection out of it. 'Consumes' ranges array (modifying + // it). + function normalizeSelection(cm, ranges, primIndex) { + var mayTouch = cm && cm.options.selectionsMayTouch; + var prim = ranges[primIndex]; + ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }); + primIndex = indexOf(ranges, prim); + for (var i = 1; i < ranges.length; i++) { + var cur = ranges[i], prev = ranges[i - 1]; + var diff = cmp(prev.to(), cur.from()); + if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) { + var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); + var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; + if (i <= primIndex) { --primIndex; } + ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); + } + } + return new Selection(ranges, primIndex) + } + + function simpleSelection(anchor, head) { + return new Selection([new Range(anchor, head || anchor)], 0) + } + + // Compute the position of the end of a change (its 'to' property + // refers to the pre-change end). + function changeEnd(change) { + if (!change.text) { return change.to } + return Pos(change.from.line + change.text.length - 1, + lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) + } + + // Adjust a position to refer to the post-change position of the + // same text, or the end of the change if the change covers it. + function adjustForChange(pos, change) { + if (cmp(pos, change.from) < 0) { return pos } + if (cmp(pos, change.to) <= 0) { return changeEnd(change) } + + var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; + if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; } + return Pos(line, ch) + } + + function computeSelAfterChange(doc, change) { + var out = []; + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i]; + out.push(new Range(adjustForChange(range.anchor, change), + adjustForChange(range.head, change))); + } + return normalizeSelection(doc.cm, out, doc.sel.primIndex) + } + + function offsetPos(pos, old, nw) { + if (pos.line == old.line) + { return Pos(nw.line, pos.ch - old.ch + nw.ch) } + else + { return Pos(nw.line + (pos.line - old.line), pos.ch) } + } + + // Used by replaceSelections to allow moving the selection to the + // start or around the replaced test. Hint may be "start" or "around". + function computeReplacedSel(doc, changes, hint) { + var out = []; + var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + var from = offsetPos(change.from, oldPrev, newPrev); + var to = offsetPos(changeEnd(change), oldPrev, newPrev); + oldPrev = change.to; + newPrev = to; + if (hint == "around") { + var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; + out[i] = new Range(inv ? to : from, inv ? from : to); + } else { + out[i] = new Range(from, from); + } + } + return new Selection(out, doc.sel.primIndex) + } + + // Used to get the editor into a consistent state again when options change. + + function loadMode(cm) { + cm.doc.mode = getMode(cm.options, cm.doc.modeOption); + resetModeState(cm); + } + + function resetModeState(cm) { + cm.doc.iter(function (line) { + if (line.stateAfter) { line.stateAfter = null; } + if (line.styles) { line.styles = null; } + }); + cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first; + startWorker(cm, 100); + cm.state.modeGen++; + if (cm.curOp) { regChange(cm); } + } + + // DOCUMENT DATA STRUCTURE + + // By default, updates that start and end at the beginning of a line + // are treated specially, in order to make the association of line + // widgets and marker elements with the text behave more intuitive. + function isWholeLineUpdate(doc, change) { + return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && + (!doc.cm || doc.cm.options.wholeLineUpdateBefore) + } + + // Perform a change on the document data structure. + function updateDoc(doc, change, markedSpans, estimateHeight$$1) { + function spansFor(n) {return markedSpans ? markedSpans[n] : null} + function update(line, text, spans) { + updateLine(line, text, spans, estimateHeight$$1); + signalLater(line, "change", line, change); + } + function linesFor(start, end) { + var result = []; + for (var i = start; i < end; ++i) + { result.push(new Line(text[i], spansFor(i), estimateHeight$$1)); } + return result + } + + var from = change.from, to = change.to, text = change.text; + var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); + var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; + + // Adjust the line structure + if (change.full) { + doc.insert(0, linesFor(0, text.length)); + doc.remove(text.length, doc.size - text.length); + } else if (isWholeLineUpdate(doc, change)) { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = linesFor(0, text.length - 1); + update(lastLine, lastLine.text, lastSpans); + if (nlines) { doc.remove(from.line, nlines); } + if (added.length) { doc.insert(from.line, added); } + } else if (firstLine == lastLine) { + if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); + } else { + var added$1 = linesFor(1, text.length - 1); + added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight$$1)); + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + doc.insert(from.line + 1, added$1); + } + } else if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); + doc.remove(from.line + 1, nlines); + } else { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); + var added$2 = linesFor(1, text.length - 1); + if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); } + doc.insert(from.line + 1, added$2); + } + + signalLater(doc, "change", doc, change); + } + + // Call f for all linked documents. + function linkedDocs(doc, f, sharedHistOnly) { + function propagate(doc, skip, sharedHist) { + if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { + var rel = doc.linked[i]; + if (rel.doc == skip) { continue } + var shared = sharedHist && rel.sharedHist; + if (sharedHistOnly && !shared) { continue } + f(rel.doc, shared); + propagate(rel.doc, doc, shared); + } } + } + propagate(doc, null, true); + } + + // Attach a document to an editor. + function attachDoc(cm, doc) { + if (doc.cm) { throw new Error("This document is already in use.") } + cm.doc = doc; + doc.cm = cm; + estimateLineHeights(cm); + loadMode(cm); + setDirectionClass(cm); + if (!cm.options.lineWrapping) { findMaxLine(cm); } + cm.options.mode = doc.modeOption; + regChange(cm); + } + + function setDirectionClass(cm) { + (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl"); + } + + function directionChanged(cm) { + runInOp(cm, function () { + setDirectionClass(cm); + regChange(cm); + }); + } + + function History(startGen) { + // Arrays of change events and selections. Doing something adds an + // event to done and clears undo. Undoing moves events from done + // to undone, redoing moves them in the other direction. + this.done = []; this.undone = []; + this.undoDepth = Infinity; + // Used to track when changes can be merged into a single undo + // event + this.lastModTime = this.lastSelTime = 0; + this.lastOp = this.lastSelOp = null; + this.lastOrigin = this.lastSelOrigin = null; + // Used by the isClean() method + this.generation = this.maxGeneration = startGen || 1; + } + + // Create a history change event from an updateDoc-style change + // object. + function historyChangeFromChange(doc, change) { + var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; + attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); + linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true); + return histChange + } + + // Pop all selection events off the end of a history array. Stop at + // a change event. + function clearSelectionEvents(array) { + while (array.length) { + var last = lst(array); + if (last.ranges) { array.pop(); } + else { break } + } + } + + // Find the top change event in the history. Pop off selection + // events that are in the way. + function lastChangeEvent(hist, force) { + if (force) { + clearSelectionEvents(hist.done); + return lst(hist.done) + } else if (hist.done.length && !lst(hist.done).ranges) { + return lst(hist.done) + } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { + hist.done.pop(); + return lst(hist.done) + } + } + + // Register a change in the history. Merges changes that are within + // a single operation, or are close together with an origin that + // allows merging (starting with "+") into a single event. + function addChangeToHistory(doc, change, selAfter, opId) { + var hist = doc.history; + hist.undone.length = 0; + var time = +new Date, cur; + var last; + + if ((hist.lastOp == opId || + hist.lastOrigin == change.origin && change.origin && + ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) || + change.origin.charAt(0) == "*")) && + (cur = lastChangeEvent(hist, hist.lastOp == opId))) { + // Merge this change into the last event + last = lst(cur.changes); + if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { + // Optimized case for simple insertion -- don't want to add + // new changesets for every character typed + last.to = changeEnd(change); + } else { + // Add new sub-event + cur.changes.push(historyChangeFromChange(doc, change)); + } + } else { + // Can not be merged, start a new event. + var before = lst(hist.done); + if (!before || !before.ranges) + { pushSelectionToHistory(doc.sel, hist.done); } + cur = {changes: [historyChangeFromChange(doc, change)], + generation: hist.generation}; + hist.done.push(cur); + while (hist.done.length > hist.undoDepth) { + hist.done.shift(); + if (!hist.done[0].ranges) { hist.done.shift(); } + } + } + hist.done.push(selAfter); + hist.generation = ++hist.maxGeneration; + hist.lastModTime = hist.lastSelTime = time; + hist.lastOp = hist.lastSelOp = opId; + hist.lastOrigin = hist.lastSelOrigin = change.origin; + + if (!last) { signal(doc, "historyAdded"); } + } + + function selectionEventCanBeMerged(doc, origin, prev, sel) { + var ch = origin.charAt(0); + return ch == "*" || + ch == "+" && + prev.ranges.length == sel.ranges.length && + prev.somethingSelected() == sel.somethingSelected() && + new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) + } + + // Called whenever the selection changes, sets the new selection as + // the pending selection in the history, and pushes the old pending + // selection into the 'done' array when it was significantly + // different (in number of selected ranges, emptiness, or time). + function addSelectionToHistory(doc, sel, opId, options) { + var hist = doc.history, origin = options && options.origin; + + // A new event is started when the previous origin does not match + // the current, or the origins don't allow matching. Origins + // starting with * are always merged, those starting with + are + // merged when similar and close together in time. + if (opId == hist.lastSelOp || + (origin && hist.lastSelOrigin == origin && + (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || + selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) + { hist.done[hist.done.length - 1] = sel; } + else + { pushSelectionToHistory(sel, hist.done); } + + hist.lastSelTime = +new Date; + hist.lastSelOrigin = origin; + hist.lastSelOp = opId; + if (options && options.clearRedo !== false) + { clearSelectionEvents(hist.undone); } + } + + function pushSelectionToHistory(sel, dest) { + var top = lst(dest); + if (!(top && top.ranges && top.equals(sel))) + { dest.push(sel); } + } + + // Used to store marked span information in the history. + function attachLocalSpans(doc, change, from, to) { + var existing = change["spans_" + doc.id], n = 0; + doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { + if (line.markedSpans) + { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; } + ++n; + }); + } + + // When un/re-doing restores text containing marked spans, those + // that have been explicitly cleared should not be restored. + function removeClearedSpans(spans) { + if (!spans) { return null } + var out; + for (var i = 0; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } } + else if (out) { out.push(spans[i]); } + } + return !out ? spans : out.length ? out : null + } + + // Retrieve and filter the old marked spans stored in a change event. + function getOldSpans(doc, change) { + var found = change["spans_" + doc.id]; + if (!found) { return null } + var nw = []; + for (var i = 0; i < change.text.length; ++i) + { nw.push(removeClearedSpans(found[i])); } + return nw + } + + // Used for un/re-doing changes from the history. Combines the + // result of computing the existing spans with the set of spans that + // existed in the history (so that deleting around a span and then + // undoing brings back the span). + function mergeOldSpans(doc, change) { + var old = getOldSpans(doc, change); + var stretched = stretchSpansOverChange(doc, change); + if (!old) { return stretched } + if (!stretched) { return old } + + for (var i = 0; i < old.length; ++i) { + var oldCur = old[i], stretchCur = stretched[i]; + if (oldCur && stretchCur) { + spans: for (var j = 0; j < stretchCur.length; ++j) { + var span = stretchCur[j]; + for (var k = 0; k < oldCur.length; ++k) + { if (oldCur[k].marker == span.marker) { continue spans } } + oldCur.push(span); + } + } else if (stretchCur) { + old[i] = stretchCur; + } + } + return old + } + + // Used both to provide a JSON-safe object in .getHistory, and, when + // detaching a document, to split the history in two + function copyHistoryArray(events, newGroup, instantiateSel) { + var copy = []; + for (var i = 0; i < events.length; ++i) { + var event = events[i]; + if (event.ranges) { + copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); + continue + } + var changes = event.changes, newChanges = []; + copy.push({changes: newChanges}); + for (var j = 0; j < changes.length; ++j) { + var change = changes[j], m = (void 0); + newChanges.push({from: change.from, to: change.to, text: change.text}); + if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { + if (indexOf(newGroup, Number(m[1])) > -1) { + lst(newChanges)[prop] = change[prop]; + delete change[prop]; + } + } } } + } + } + return copy + } + + // The 'scroll' parameter given to many of these indicated whether + // the new cursor position should be scrolled into view after + // modifying the selection. + + // If shift is held or the extend flag is set, extends a range to + // include a given position (and optionally a second position). + // Otherwise, simply returns the range between the given positions. + // Used for cursor motion and such. + function extendRange(range, head, other, extend) { + if (extend) { + var anchor = range.anchor; + if (other) { + var posBefore = cmp(head, anchor) < 0; + if (posBefore != (cmp(other, anchor) < 0)) { + anchor = head; + head = other; + } else if (posBefore != (cmp(head, other) < 0)) { + head = other; + } + } + return new Range(anchor, head) + } else { + return new Range(other || head, head) + } + } + + // Extend the primary selection range, discard the rest. + function extendSelection(doc, head, other, options, extend) { + if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); } + setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options); + } + + // Extend all selections (pos is an array of selections with length + // equal the number of selections) + function extendSelections(doc, heads, options) { + var out = []; + var extend = doc.cm && (doc.cm.display.shift || doc.extend); + for (var i = 0; i < doc.sel.ranges.length; i++) + { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); } + var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex); + setSelection(doc, newSel, options); + } + + // Updates a single range in the selection. + function replaceOneSelection(doc, i, range, options) { + var ranges = doc.sel.ranges.slice(0); + ranges[i] = range; + setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options); + } + + // Reset the selection to a single range. + function setSimpleSelection(doc, anchor, head, options) { + setSelection(doc, simpleSelection(anchor, head), options); + } + + // Give beforeSelectionChange handlers a change to influence a + // selection update. + function filterSelectionChange(doc, sel, options) { + var obj = { + ranges: sel.ranges, + update: function(ranges) { + var this$1 = this; + + this.ranges = []; + for (var i = 0; i < ranges.length; i++) + { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), + clipPos(doc, ranges[i].head)); } + }, + origin: options && options.origin + }; + signal(doc, "beforeSelectionChange", doc, obj); + if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); } + if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) } + else { return sel } + } + + function setSelectionReplaceHistory(doc, sel, options) { + var done = doc.history.done, last = lst(done); + if (last && last.ranges) { + done[done.length - 1] = sel; + setSelectionNoUndo(doc, sel, options); + } else { + setSelection(doc, sel, options); + } + } + + // Set a new selection. + function setSelection(doc, sel, options) { + setSelectionNoUndo(doc, sel, options); + addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); + } + + function setSelectionNoUndo(doc, sel, options) { + if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) + { sel = filterSelectionChange(doc, sel, options); } + + var bias = options && options.bias || + (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); + setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); + + if (!(options && options.scroll === false) && doc.cm) + { ensureCursorVisible(doc.cm); } + } + + function setSelectionInner(doc, sel) { + if (sel.equals(doc.sel)) { return } + + doc.sel = sel; + + if (doc.cm) { + doc.cm.curOp.updateInput = 1; + doc.cm.curOp.selectionChanged = true; + signalCursorActivity(doc.cm); + } + signalLater(doc, "cursorActivity", doc); + } + + // Verify that the selection does not partially select any atomic + // marked ranges. + function reCheckSelection(doc) { + setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)); + } + + // Return a selection that does not partially select any atomic + // ranges. + function skipAtomicInSelection(doc, sel, bias, mayClear) { + var out; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; + var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); + var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear); + if (out || newAnchor != range.anchor || newHead != range.head) { + if (!out) { out = sel.ranges.slice(0, i); } + out[i] = new Range(newAnchor, newHead); + } + } + return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel + } + + function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { + var line = getLine(doc, pos.line); + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], m = sp.marker; + + // Determine if we should prevent the cursor being placed to the left/right of an atomic marker + // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it + // is with selectLeft/Right + var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft; + var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight; + + if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && + (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + if (mayClear) { + signal(m, "beforeCursorEnter"); + if (m.explicitlyCleared) { + if (!line.markedSpans) { break } + else {--i; continue} + } + } + if (!m.atomic) { continue } + + if (oldPos) { + var near = m.find(dir < 0 ? 1 : -1), diff = (void 0); + if (dir < 0 ? preventCursorRight : preventCursorLeft) + { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); } + if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) + { return skipAtomicInner(doc, near, pos, dir, mayClear) } + } + + var far = m.find(dir < 0 ? -1 : 1); + if (dir < 0 ? preventCursorLeft : preventCursorRight) + { far = movePos(doc, far, dir, far.line == pos.line ? line : null); } + return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null + } + } } + return pos + } + + // Ensure a given position is not inside an atomic range. + function skipAtomic(doc, pos, oldPos, bias, mayClear) { + var dir = bias || 1; + var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || + skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)); + if (!found) { + doc.cantEdit = true; + return Pos(doc.first, 0) + } + return found + } + + function movePos(doc, pos, dir, line) { + if (dir < 0 && pos.ch == 0) { + if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } + else { return null } + } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { + if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } + else { return null } + } else { + return new Pos(pos.line, pos.ch + dir) + } + } + + function selectAll(cm) { + cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll); + } + + // UPDATING + + // Allow "beforeChange" event handlers to influence a change + function filterChange(doc, change, update) { + var obj = { + canceled: false, + from: change.from, + to: change.to, + text: change.text, + origin: change.origin, + cancel: function () { return obj.canceled = true; } + }; + if (update) { obj.update = function (from, to, text, origin) { + if (from) { obj.from = clipPos(doc, from); } + if (to) { obj.to = clipPos(doc, to); } + if (text) { obj.text = text; } + if (origin !== undefined) { obj.origin = origin; } + }; } + signal(doc, "beforeChange", doc, obj); + if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); } + + if (obj.canceled) { + if (doc.cm) { doc.cm.curOp.updateInput = 2; } + return null + } + return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} + } + + // Apply a change to a document, and add it to the document's + // history, and propagating it to all linked documents. + function makeChange(doc, change, ignoreReadOnly) { + if (doc.cm) { + if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } + if (doc.cm.state.suppressEdits) { return } + } + + if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { + change = filterChange(doc, change, true); + if (!change) { return } + } + + // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); + if (split) { + for (var i = split.length - 1; i >= 0; --i) + { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); } + } else { + makeChangeInner(doc, change); + } + } + + function makeChangeInner(doc, change) { + if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } + var selAfter = computeSelAfterChange(doc, change); + addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); + + makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); + var rebased = []; + + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); + }); + } + + // Revert a change stored in a document's history. + function makeChangeFromHistory(doc, type, allowSelectionOnly) { + var suppress = doc.cm && doc.cm.state.suppressEdits; + if (suppress && !allowSelectionOnly) { return } + + var hist = doc.history, event, selAfter = doc.sel; + var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; + + // Verify that there is a useable event (so that ctrl-z won't + // needlessly clear selection events) + var i = 0; + for (; i < source.length; i++) { + event = source[i]; + if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) + { break } + } + if (i == source.length) { return } + hist.lastOrigin = hist.lastSelOrigin = null; + + for (;;) { + event = source.pop(); + if (event.ranges) { + pushSelectionToHistory(event, dest); + if (allowSelectionOnly && !event.equals(doc.sel)) { + setSelection(doc, event, {clearRedo: false}); + return + } + selAfter = event; + } else if (suppress) { + source.push(event); + return + } else { break } + } + + // Build up a reverse change object to add to the opposite history + // stack (redo when undoing, and vice versa). + var antiChanges = []; + pushSelectionToHistory(selAfter, dest); + dest.push({changes: antiChanges, generation: hist.generation}); + hist.generation = event.generation || ++hist.maxGeneration; + + var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); + + var loop = function ( i ) { + var change = event.changes[i]; + change.origin = type; + if (filter && !filterChange(doc, change, false)) { + source.length = 0; + return {} + } + + antiChanges.push(historyChangeFromChange(doc, change)); + + var after = i ? computeSelAfterChange(doc, change) : lst(source); + makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); + if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); } + var rebased = []; + + // Propagate to the linked documents + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); + }); + }; + + for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { + var returned = loop( i$1 ); + + if ( returned ) return returned.v; + } + } + + // Sub-views need their line numbers shifted when text is added + // above or below them in the parent document. + function shiftDoc(doc, distance) { + if (distance == 0) { return } + doc.first += distance; + doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( + Pos(range.anchor.line + distance, range.anchor.ch), + Pos(range.head.line + distance, range.head.ch) + ); }), doc.sel.primIndex); + if (doc.cm) { + regChange(doc.cm, doc.first, doc.first - distance, distance); + for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) + { regLineChange(doc.cm, l, "gutter"); } + } + } + + // More lower-level change function, handling only a single document + // (not linked ones). + function makeChangeSingleDoc(doc, change, selAfter, spans) { + if (doc.cm && !doc.cm.curOp) + { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } + + if (change.to.line < doc.first) { + shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); + return + } + if (change.from.line > doc.lastLine()) { return } + + // Clip the change to the size of this doc + if (change.from.line < doc.first) { + var shift = change.text.length - 1 - (doc.first - change.from.line); + shiftDoc(doc, shift); + change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), + text: [lst(change.text)], origin: change.origin}; + } + var last = doc.lastLine(); + if (change.to.line > last) { + change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), + text: [change.text[0]], origin: change.origin}; + } + + change.removed = getBetween(doc, change.from, change.to); + + if (!selAfter) { selAfter = computeSelAfterChange(doc, change); } + if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); } + else { updateDoc(doc, change, spans); } + setSelectionNoUndo(doc, selAfter, sel_dontScroll); + + if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0))) + { doc.cantEdit = false; } + } + + // Handle the interaction of a change to a document with the editor + // that this document is part of. + function makeChangeSingleDocInEditor(cm, change, spans) { + var doc = cm.doc, display = cm.display, from = change.from, to = change.to; + + var recomputeMaxLength = false, checkWidthStart = from.line; + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); + doc.iter(checkWidthStart, to.line + 1, function (line) { + if (line == display.maxLine) { + recomputeMaxLength = true; + return true + } + }); + } + + if (doc.sel.contains(change.from, change.to) > -1) + { signalCursorActivity(cm); } + + updateDoc(doc, change, spans, estimateHeight(cm)); + + if (!cm.options.lineWrapping) { + doc.iter(checkWidthStart, from.line + change.text.length, function (line) { + var len = lineLength(line); + if (len > display.maxLineLength) { + display.maxLine = line; + display.maxLineLength = len; + display.maxLineChanged = true; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; } + } + + retreatFrontier(doc, from.line); + startWorker(cm, 400); + + var lendiff = change.text.length - (to.line - from.line) - 1; + // Remember that these lines changed, for updating the display + if (change.full) + { regChange(cm); } + else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) + { regLineChange(cm, from.line, "text"); } + else + { regChange(cm, from.line, to.line + 1, lendiff); } + + var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); + if (changeHandler || changesHandler) { + var obj = { + from: from, to: to, + text: change.text, + removed: change.removed, + origin: change.origin + }; + if (changeHandler) { signalLater(cm, "change", cm, obj); } + if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); } + } + cm.display.selForContextMenu = null; + } + + function replaceRange(doc, code, from, to, origin) { + var assign; + + if (!to) { to = from; } + if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); } + if (typeof code == "string") { code = doc.splitLines(code); } + makeChange(doc, {from: from, to: to, text: code, origin: origin}); + } + + // Rebasing/resetting history to deal with externally-sourced changes + + function rebaseHistSelSingle(pos, from, to, diff) { + if (to < pos.line) { + pos.line += diff; + } else if (from < pos.line) { + pos.line = from; + pos.ch = 0; + } + } + + // Tries to rebase an array of history events given a change in the + // document. If the change touches the same lines as the event, the + // event, and everything 'behind' it, is discarded. If the change is + // before the event, the event's positions are updated. Uses a + // copy-on-write scheme for the positions, to avoid having to + // reallocate them all on every rebase, but also avoid problems with + // shared position objects being unsafely updated. + function rebaseHistArray(array, from, to, diff) { + for (var i = 0; i < array.length; ++i) { + var sub = array[i], ok = true; + if (sub.ranges) { + if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } + for (var j = 0; j < sub.ranges.length; j++) { + rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); + rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); + } + continue + } + for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { + var cur = sub.changes[j$1]; + if (to < cur.from.line) { + cur.from = Pos(cur.from.line + diff, cur.from.ch); + cur.to = Pos(cur.to.line + diff, cur.to.ch); + } else if (from <= cur.to.line) { + ok = false; + break + } + } + if (!ok) { + array.splice(0, i + 1); + i = 0; + } + } + } + + function rebaseHist(hist, change) { + var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; + rebaseHistArray(hist.done, from, to, diff); + rebaseHistArray(hist.undone, from, to, diff); + } + + // Utility for applying a change to a line by handle or number, + // returning the number and optionally registering the line as + // changed. + function changeLine(doc, handle, changeType, op) { + var no = handle, line = handle; + if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); } + else { no = lineNo(handle); } + if (no == null) { return null } + if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); } + return line + } + + // The document is represented as a BTree consisting of leaves, with + // chunk of lines in them, and branches, with up to ten leaves or + // other branch nodes below them. The top node is always a branch + // node, and is the document object itself (meaning it has + // additional methods and properties). + // + // All nodes have parent links. The tree is used both to go from + // line numbers to line objects, and to go from objects to numbers. + // It also indexes by height, and is used to convert between height + // and line object, and to find the total height of the document. + // + // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html + + function LeafChunk(lines) { + var this$1 = this; + + this.lines = lines; + this.parent = null; + var height = 0; + for (var i = 0; i < lines.length; ++i) { + lines[i].parent = this$1; + height += lines[i].height; + } + this.height = height; + } + + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length }, + + // Remove the n lines at offset 'at'. + removeInner: function(at, n) { + var this$1 = this; + + for (var i = at, e = at + n; i < e; ++i) { + var line = this$1.lines[i]; + this$1.height -= line.height; + cleanUpLine(line); + signalLater(line, "delete"); + } + this.lines.splice(at, n); + }, + + // Helper used to collapse a small branch into a single leaf. + collapse: function(lines) { + lines.push.apply(lines, this.lines); + }, + + // Insert the given array of lines at offset 'at', count them as + // having the given height. + insertInner: function(at, lines, height) { + var this$1 = this; + + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1; } + }, + + // Used to iterate over a part of the tree. + iterN: function(at, n, op) { + var this$1 = this; + + for (var e = at + n; at < e; ++at) + { if (op(this$1.lines[at])) { return true } } + } + }; + + function BranchChunk(children) { + var this$1 = this; + + this.children = children; + var size = 0, height = 0; + for (var i = 0; i < children.length; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this$1; + } + this.size = size; + this.height = height; + this.parent = null; + } + + BranchChunk.prototype = { + chunkSize: function() { return this.size }, + + removeInner: function(at, n) { + var this$1 = this; + + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.removeInner(at, rm); + this$1.height -= oldHeight - child.height; + if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) { break } + at = 0; + } else { at -= sz; } + } + // If the result is smaller than 25 lines, ensure that it is a + // single leaf node. + if (this.size - n < 25 && + (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + + collapse: function(lines) { + var this$1 = this; + + for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines); } + }, + + insertInner: function(at, lines, height) { + var this$1 = this; + + this.size += lines.length; + this.height += height; + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertInner(at, lines, height); + if (child.lines && child.lines.length > 50) { + // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. + // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. + var remaining = child.lines.length % 25 + 25; + for (var pos = remaining; pos < child.lines.length;) { + var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); + child.height -= leaf.height; + this$1.children.splice(++i, 0, leaf); + leaf.parent = this$1; + } + child.lines = child.lines.slice(0, remaining); + this$1.maybeSpill(); + } + break + } + at -= sz; + } + }, + + // When a node has grown, check whether it should be split. + maybeSpill: function() { + if (this.children.length <= 10) { return } + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10) + me.parent.maybeSpill(); + }, + + iterN: function(at, n, op) { + var this$1 = this; + + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) { return true } + if ((n -= used) == 0) { break } + at = 0; + } else { at -= sz; } + } + } + }; + + // Line widgets are block elements displayed above or below a line. + + var LineWidget = function(doc, node, options) { + var this$1 = this; + + if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) + { this$1[opt] = options[opt]; } } } + this.doc = doc; + this.node = node; + }; + + LineWidget.prototype.clear = function () { + var this$1 = this; + + var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); + if (no == null || !ws) { return } + for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1); } } + if (!ws.length) { line.widgets = null; } + var height = widgetHeight(this); + updateLineHeight(line, Math.max(0, line.height - height)); + if (cm) { + runInOp(cm, function () { + adjustScrollWhenAboveVisible(cm, line, -height); + regLineChange(cm, no, "widget"); + }); + signalLater(cm, "lineWidgetCleared", cm, this, no); + } + }; + + LineWidget.prototype.changed = function () { + var this$1 = this; + + var oldH = this.height, cm = this.doc.cm, line = this.line; + this.height = null; + var diff = widgetHeight(this) - oldH; + if (!diff) { return } + if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); } + if (cm) { + runInOp(cm, function () { + cm.curOp.forceUpdate = true; + adjustScrollWhenAboveVisible(cm, line, diff); + signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)); + }); + } + }; + eventMixin(LineWidget); + + function adjustScrollWhenAboveVisible(cm, line, diff) { + if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) + { addToScrollTop(cm, diff); } + } + + function addLineWidget(doc, handle, node, options) { + var widget = new LineWidget(doc, node, options); + var cm = doc.cm; + if (cm && widget.noHScroll) { cm.display.alignWidgets = true; } + changeLine(doc, handle, "widget", function (line) { + var widgets = line.widgets || (line.widgets = []); + if (widget.insertAt == null) { widgets.push(widget); } + else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); } + widget.line = line; + if (cm && !lineIsHidden(doc, line)) { + var aboveVisible = heightAtLine(line) < doc.scrollTop; + updateLineHeight(line, line.height + widgetHeight(widget)); + if (aboveVisible) { addToScrollTop(cm, widget.height); } + cm.curOp.forceUpdate = true; + } + return true + }); + if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); } + return widget + } + + // TEXTMARKERS + + // Created with markText and setBookmark methods. A TextMarker is a + // handle that can be used to clear or find a marked position in the + // document. Line objects hold arrays (markedSpans) containing + // {from, to, marker} object pointing to such marker objects, and + // indicating that such a marker is present on that line. Multiple + // lines may point to the same marker when it spans across lines. + // The spans will have null for their from/to properties when the + // marker continues beyond the start/end of the line. Markers have + // links back to the lines they currently touch. + + // Collapsed markers have unique ids, in order to be able to order + // them, which is needed for uniquely determining an outer marker + // when they overlap (they may nest, but not partially overlap). + var nextMarkerId = 0; + + var TextMarker = function(doc, type) { + this.lines = []; + this.type = type; + this.doc = doc; + this.id = ++nextMarkerId; + }; + + // Clear the marker. + TextMarker.prototype.clear = function () { + var this$1 = this; + + if (this.explicitlyCleared) { return } + var cm = this.doc.cm, withOp = cm && !cm.curOp; + if (withOp) { startOperation(cm); } + if (hasHandler(this, "clear")) { + var found = this.find(); + if (found) { signalLater(this, "clear", found.from, found.to); } + } + var min = null, max = null; + for (var i = 0; i < this.lines.length; ++i) { + var line = this$1.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this$1); + if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text"); } + else if (cm) { + if (span.to != null) { max = lineNo(line); } + if (span.from != null) { min = lineNo(line); } + } + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm) + { updateLineHeight(line, textHeight(cm.display)); } + } + if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { + var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual); + if (len > cm.display.maxLineLength) { + cm.display.maxLine = visual; + cm.display.maxLineLength = len; + cm.display.maxLineChanged = true; + } + } } + + if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); } + this.lines.length = 0; + this.explicitlyCleared = true; + if (this.atomic && this.doc.cantEdit) { + this.doc.cantEdit = false; + if (cm) { reCheckSelection(cm.doc); } + } + if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); } + if (withOp) { endOperation(cm); } + if (this.parent) { this.parent.clear(); } + }; + + // Find the position of the marker in the document. Returns a {from, + // to} object by default. Side can be passed to get a specific side + // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the + // Pos objects returned contain a line object, rather than a line + // number (used to prevent looking up the same line twice). + TextMarker.prototype.find = function (side, lineObj) { + var this$1 = this; + + if (side == null && this.type == "bookmark") { side = 1; } + var from, to; + for (var i = 0; i < this.lines.length; ++i) { + var line = this$1.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this$1); + if (span.from != null) { + from = Pos(lineObj ? line : lineNo(line), span.from); + if (side == -1) { return from } + } + if (span.to != null) { + to = Pos(lineObj ? line : lineNo(line), span.to); + if (side == 1) { return to } + } + } + return from && {from: from, to: to} + }; + + // Signals that the marker's widget changed, and surrounding layout + // should be recomputed. + TextMarker.prototype.changed = function () { + var this$1 = this; + + var pos = this.find(-1, true), widget = this, cm = this.doc.cm; + if (!pos || !cm) { return } + runInOp(cm, function () { + var line = pos.line, lineN = lineNo(pos.line); + var view = findViewForLine(cm, lineN); + if (view) { + clearLineMeasurementCacheFor(view); + cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; + } + cm.curOp.updateMaxLine = true; + if (!lineIsHidden(widget.doc, line) && widget.height != null) { + var oldHeight = widget.height; + widget.height = null; + var dHeight = widgetHeight(widget) - oldHeight; + if (dHeight) + { updateLineHeight(line, line.height + dHeight); } + } + signalLater(cm, "markerChanged", cm, this$1); + }); + }; + + TextMarker.prototype.attachLine = function (line) { + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) + { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); } + } + this.lines.push(line); + }; + + TextMarker.prototype.detachLine = function (line) { + this.lines.splice(indexOf(this.lines, line), 1); + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp + ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); + } + }; + eventMixin(TextMarker); + + // Create a marker, wire it up to the right lines, and + function markText(doc, from, to, options, type) { + // Shared markers (across linked documents) are handled separately + // (markTextShared will call out to this again, once per + // document). + if (options && options.shared) { return markTextShared(doc, from, to, options, type) } + // Ensure we are in an operation. + if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } + + var marker = new TextMarker(doc, type), diff = cmp(from, to); + if (options) { copyObj(options, marker, false); } + // Don't connect empty markers unless clearWhenEmpty is false + if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) + { return marker } + if (marker.replacedWith) { + // Showing up as a widget implies collapsed (widget replaces text) + marker.collapsed = true; + marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget"); + if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); } + if (options.insertLeft) { marker.widgetNode.insertLeft = true; } + } + if (marker.collapsed) { + if (conflictingCollapsedRange(doc, from.line, from, to, marker) || + from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) + { throw new Error("Inserting collapsed marker partially overlapping an existing one") } + seeCollapsedSpans(); + } + + if (marker.addToHistory) + { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); } + + var curLine = from.line, cm = doc.cm, updateMaxLine; + doc.iter(curLine, to.line + 1, function (line) { + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) + { updateMaxLine = true; } + if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); } + addMarkedSpan(line, new MarkedSpan(marker, + curLine == from.line ? from.ch : null, + curLine == to.line ? to.ch : null)); + ++curLine; + }); + // lineIsHidden depends on the presence of the spans, so needs a second pass + if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { + if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); } + }); } + + if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); } + + if (marker.readOnly) { + seeReadOnlySpans(); + if (doc.history.done.length || doc.history.undone.length) + { doc.clearHistory(); } + } + if (marker.collapsed) { + marker.id = ++nextMarkerId; + marker.atomic = true; + } + if (cm) { + // Sync editor state + if (updateMaxLine) { cm.curOp.updateMaxLine = true; } + if (marker.collapsed) + { regChange(cm, from.line, to.line + 1); } + else if (marker.className || marker.startStyle || marker.endStyle || marker.css || + marker.attributes || marker.title) + { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } } + if (marker.atomic) { reCheckSelection(cm.doc); } + signalLater(cm, "markerAdded", cm, marker); + } + return marker + } + + // SHARED TEXTMARKERS + + // A shared marker spans multiple linked documents. It is + // implemented as a meta-marker-object controlling multiple normal + // markers. + var SharedTextMarker = function(markers, primary) { + var this$1 = this; + + this.markers = markers; + this.primary = primary; + for (var i = 0; i < markers.length; ++i) + { markers[i].parent = this$1; } + }; + + SharedTextMarker.prototype.clear = function () { + var this$1 = this; + + if (this.explicitlyCleared) { return } + this.explicitlyCleared = true; + for (var i = 0; i < this.markers.length; ++i) + { this$1.markers[i].clear(); } + signalLater(this, "clear"); + }; + + SharedTextMarker.prototype.find = function (side, lineObj) { + return this.primary.find(side, lineObj) + }; + eventMixin(SharedTextMarker); + + function markTextShared(doc, from, to, options, type) { + options = copyObj(options); + options.shared = false; + var markers = [markText(doc, from, to, options, type)], primary = markers[0]; + var widget = options.widgetNode; + linkedDocs(doc, function (doc) { + if (widget) { options.widgetNode = widget.cloneNode(true); } + markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); + for (var i = 0; i < doc.linked.length; ++i) + { if (doc.linked[i].isParent) { return } } + primary = lst(markers); + }); + return new SharedTextMarker(markers, primary) + } + + function findSharedMarkers(doc) { + return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) + } + + function copySharedMarkers(doc, markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], pos = marker.find(); + var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); + if (cmp(mFrom, mTo)) { + var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); + marker.markers.push(subMark); + subMark.parent = marker; + } + } + } + + function detachSharedMarkers(markers) { + var loop = function ( i ) { + var marker = markers[i], linked = [marker.primary.doc]; + linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }); + for (var j = 0; j < marker.markers.length; j++) { + var subMarker = marker.markers[j]; + if (indexOf(linked, subMarker.doc) == -1) { + subMarker.parent = null; + marker.markers.splice(j--, 1); + } + } + }; + + for (var i = 0; i < markers.length; i++) loop( i ); + } + + var nextDocId = 0; + var Doc = function(text, mode, firstLine, lineSep, direction) { + if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) } + if (firstLine == null) { firstLine = 0; } + + BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); + this.first = firstLine; + this.scrollTop = this.scrollLeft = 0; + this.cantEdit = false; + this.cleanGeneration = 1; + this.modeFrontier = this.highlightFrontier = firstLine; + var start = Pos(firstLine, 0); + this.sel = simpleSelection(start); + this.history = new History(null); + this.id = ++nextDocId; + this.modeOption = mode; + this.lineSep = lineSep; + this.direction = (direction == "rtl") ? "rtl" : "ltr"; + this.extend = false; + + if (typeof text == "string") { text = this.splitLines(text); } + updateDoc(this, {from: start, to: start, text: text}); + setSelection(this, simpleSelection(start), sel_dontScroll); + }; + + Doc.prototype = createObj(BranchChunk.prototype, { + constructor: Doc, + // Iterate over the document. Supports two forms -- with only one + // argument, it calls that for each line in the document. With + // three, it iterates over the range given by the first two (with + // the second being non-inclusive). + iter: function(from, to, op) { + if (op) { this.iterN(from - this.first, to - from, op); } + else { this.iterN(this.first, this.first + this.size, from); } + }, + + // Non-public interface for adding and removing lines. + insert: function(at, lines) { + var height = 0; + for (var i = 0; i < lines.length; ++i) { height += lines[i].height; } + this.insertInner(at - this.first, lines, height); + }, + remove: function(at, n) { this.removeInner(at - this.first, n); }, + + // From here, the methods are part of the public interface. Most + // are also available from CodeMirror (editor) instances. + + getValue: function(lineSep) { + var lines = getLines(this, this.first, this.first + this.size); + if (lineSep === false) { return lines } + return lines.join(lineSep || this.lineSeparator()) + }, + setValue: docMethodOp(function(code) { + var top = Pos(this.first, 0), last = this.first + this.size - 1; + makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), + text: this.splitLines(code), origin: "setValue", full: true}, true); + if (this.cm) { scrollToCoords(this.cm, 0, 0); } + setSelection(this, simpleSelection(top), sel_dontScroll); + }), + replaceRange: function(code, from, to, origin) { + from = clipPos(this, from); + to = to ? clipPos(this, to) : from; + replaceRange(this, code, from, to, origin); + }, + getRange: function(from, to, lineSep) { + var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); + if (lineSep === false) { return lines } + return lines.join(lineSep || this.lineSeparator()) + }, + + getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, + + getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, + getLineNumber: function(line) {return lineNo(line)}, + + getLineHandleVisualStart: function(line) { + if (typeof line == "number") { line = getLine(this, line); } + return visualLine(line) + }, + + lineCount: function() {return this.size}, + firstLine: function() {return this.first}, + lastLine: function() {return this.first + this.size - 1}, + + clipPos: function(pos) {return clipPos(this, pos)}, + + getCursor: function(start) { + var range$$1 = this.sel.primary(), pos; + if (start == null || start == "head") { pos = range$$1.head; } + else if (start == "anchor") { pos = range$$1.anchor; } + else if (start == "end" || start == "to" || start === false) { pos = range$$1.to(); } + else { pos = range$$1.from(); } + return pos + }, + listSelections: function() { return this.sel.ranges }, + somethingSelected: function() {return this.sel.somethingSelected()}, + + setCursor: docMethodOp(function(line, ch, options) { + setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); + }), + setSelection: docMethodOp(function(anchor, head, options) { + setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); + }), + extendSelection: docMethodOp(function(head, other, options) { + extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); + }), + extendSelections: docMethodOp(function(heads, options) { + extendSelections(this, clipPosArray(this, heads), options); + }), + extendSelectionsBy: docMethodOp(function(f, options) { + var heads = map(this.sel.ranges, f); + extendSelections(this, clipPosArray(this, heads), options); + }), + setSelections: docMethodOp(function(ranges, primary, options) { + var this$1 = this; + + if (!ranges.length) { return } + var out = []; + for (var i = 0; i < ranges.length; i++) + { out[i] = new Range(clipPos(this$1, ranges[i].anchor), + clipPos(this$1, ranges[i].head)); } + if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); } + setSelection(this, normalizeSelection(this.cm, out, primary), options); + }), + addSelection: docMethodOp(function(anchor, head, options) { + var ranges = this.sel.ranges.slice(0); + ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); + setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options); + }), + + getSelection: function(lineSep) { + var this$1 = this; + + var ranges = this.sel.ranges, lines; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()); + lines = lines ? lines.concat(sel) : sel; + } + if (lineSep === false) { return lines } + else { return lines.join(lineSep || this.lineSeparator()) } + }, + getSelections: function(lineSep) { + var this$1 = this; + + var parts = [], ranges = this.sel.ranges; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()); + if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()); } + parts[i] = sel; + } + return parts + }, + replaceSelection: function(code, collapse, origin) { + var dup = []; + for (var i = 0; i < this.sel.ranges.length; i++) + { dup[i] = code; } + this.replaceSelections(dup, collapse, origin || "+input"); + }, + replaceSelections: docMethodOp(function(code, collapse, origin) { + var this$1 = this; + + var changes = [], sel = this.sel; + for (var i = 0; i < sel.ranges.length; i++) { + var range$$1 = sel.ranges[i]; + changes[i] = {from: range$$1.from(), to: range$$1.to(), text: this$1.splitLines(code[i]), origin: origin}; + } + var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); + for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) + { makeChange(this$1, changes[i$1]); } + if (newSel) { setSelectionReplaceHistory(this, newSel); } + else if (this.cm) { ensureCursorVisible(this.cm); } + }), + undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), + redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), + undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), + redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), + + setExtending: function(val) {this.extend = val;}, + getExtending: function() {return this.extend}, + + historySize: function() { + var hist = this.history, done = 0, undone = 0; + for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } } + for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } } + return {undo: done, redo: undone} + }, + clearHistory: function() {this.history = new History(this.history.maxGeneration);}, + + markClean: function() { + this.cleanGeneration = this.changeGeneration(true); + }, + changeGeneration: function(forceSplit) { + if (forceSplit) + { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; } + return this.history.generation + }, + isClean: function (gen) { + return this.history.generation == (gen || this.cleanGeneration) + }, + + getHistory: function() { + return {done: copyHistoryArray(this.history.done), + undone: copyHistoryArray(this.history.undone)} + }, + setHistory: function(histData) { + var hist = this.history = new History(this.history.maxGeneration); + hist.done = copyHistoryArray(histData.done.slice(0), null, true); + hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); + }, + + setGutterMarker: docMethodOp(function(line, gutterID, value) { + return changeLine(this, line, "gutter", function (line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}); + markers[gutterID] = value; + if (!value && isEmpty(markers)) { line.gutterMarkers = null; } + return true + }) + }), + + clearGutter: docMethodOp(function(gutterID) { + var this$1 = this; + + this.iter(function (line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + changeLine(this$1, line, "gutter", function () { + line.gutterMarkers[gutterID] = null; + if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; } + return true + }); + } + }); + }), + + lineInfo: function(line) { + var n; + if (typeof line == "number") { + if (!isLine(this, line)) { return null } + n = line; + line = getLine(this, line); + if (!line) { return null } + } else { + n = lineNo(line); + if (n == null) { return null } + } + return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, + textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, + widgets: line.widgets} + }, + + addLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + if (!line[prop]) { line[prop] = cls; } + else if (classTest(cls).test(line[prop])) { return false } + else { line[prop] += " " + cls; } + return true + }) + }), + removeLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + var cur = line[prop]; + if (!cur) { return false } + else if (cls == null) { line[prop] = null; } + else { + var found = cur.match(classTest(cls)); + if (!found) { return false } + var end = found.index + found[0].length; + line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; + } + return true + }) + }), + + addLineWidget: docMethodOp(function(handle, node, options) { + return addLineWidget(this, handle, node, options) + }), + removeLineWidget: function(widget) { widget.clear(); }, + + markText: function(from, to, options) { + return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") + }, + setBookmark: function(pos, options) { + var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft, + clearWhenEmpty: false, shared: options && options.shared, + handleMouseEvents: options && options.handleMouseEvents}; + pos = clipPos(this, pos); + return markText(this, pos, pos, realOpts, "bookmark") + }, + findMarksAt: function(pos) { + pos = clipPos(this, pos); + var markers = [], spans = getLine(this, pos.line).markedSpans; + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + { markers.push(span.marker.parent || span.marker); } + } } + return markers + }, + findMarks: function(from, to, filter) { + from = clipPos(this, from); to = clipPos(this, to); + var found = [], lineNo$$1 = from.line; + this.iter(from.line, to.line + 1, function (line) { + var spans = line.markedSpans; + if (spans) { for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + if (!(span.to != null && lineNo$$1 == from.line && from.ch >= span.to || + span.from == null && lineNo$$1 != from.line || + span.from != null && lineNo$$1 == to.line && span.from >= to.ch) && + (!filter || filter(span.marker))) + { found.push(span.marker.parent || span.marker); } + } } + ++lineNo$$1; + }); + return found + }, + getAllMarks: function() { + var markers = []; + this.iter(function (line) { + var sps = line.markedSpans; + if (sps) { for (var i = 0; i < sps.length; ++i) + { if (sps[i].from != null) { markers.push(sps[i].marker); } } } + }); + return markers + }, + + posFromIndex: function(off) { + var ch, lineNo$$1 = this.first, sepSize = this.lineSeparator().length; + this.iter(function (line) { + var sz = line.text.length + sepSize; + if (sz > off) { ch = off; return true } + off -= sz; + ++lineNo$$1; + }); + return clipPos(this, Pos(lineNo$$1, ch)) + }, + indexFromPos: function (coords) { + coords = clipPos(this, coords); + var index = coords.ch; + if (coords.line < this.first || coords.ch < 0) { return 0 } + var sepSize = this.lineSeparator().length; + this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value + index += line.text.length + sepSize; + }); + return index + }, + + copy: function(copyHistory) { + var doc = new Doc(getLines(this, this.first, this.first + this.size), + this.modeOption, this.first, this.lineSep, this.direction); + doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; + doc.sel = this.sel; + doc.extend = false; + if (copyHistory) { + doc.history.undoDepth = this.history.undoDepth; + doc.setHistory(this.getHistory()); + } + return doc + }, + + linkedDoc: function(options) { + if (!options) { options = {}; } + var from = this.first, to = this.first + this.size; + if (options.from != null && options.from > from) { from = options.from; } + if (options.to != null && options.to < to) { to = options.to; } + var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction); + if (options.sharedHist) { copy.history = this.history + ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); + copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; + copySharedMarkers(copy, findSharedMarkers(this)); + return copy + }, + unlinkDoc: function(other) { + var this$1 = this; + + if (other instanceof CodeMirror) { other = other.doc; } + if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { + var link = this$1.linked[i]; + if (link.doc != other) { continue } + this$1.linked.splice(i, 1); + other.unlinkDoc(this$1); + detachSharedMarkers(findSharedMarkers(this$1)); + break + } } + // If the histories were shared, split them again + if (other.history == this.history) { + var splitIds = [other.id]; + linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true); + other.history = new History(null); + other.history.done = copyHistoryArray(this.history.done, splitIds); + other.history.undone = copyHistoryArray(this.history.undone, splitIds); + } + }, + iterLinkedDocs: function(f) {linkedDocs(this, f);}, + + getMode: function() {return this.mode}, + getEditor: function() {return this.cm}, + + splitLines: function(str) { + if (this.lineSep) { return str.split(this.lineSep) } + return splitLinesAuto(str) + }, + lineSeparator: function() { return this.lineSep || "\n" }, + + setDirection: docMethodOp(function (dir) { + if (dir != "rtl") { dir = "ltr"; } + if (dir == this.direction) { return } + this.direction = dir; + this.iter(function (line) { return line.order = null; }); + if (this.cm) { directionChanged(this.cm); } + }) + }); + + // Public alias. + Doc.prototype.eachLine = Doc.prototype.iter; + + // Kludge to work around strange IE behavior where it'll sometimes + // re-fire a series of drag-related events right after the drop (#1551) + var lastDrop = 0; + + function onDrop(e) { + var cm = this; + clearDragCursor(cm); + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) + { return } + e_preventDefault(e); + if (ie) { lastDrop = +new Date; } + var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; + if (!pos || cm.isReadOnly()) { return } + // Might be a file drop, in which case we simply extract the text + // and insert it. + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0; + var loadFile = function (file, i) { + if (cm.options.allowDropFileTypes && + indexOf(cm.options.allowDropFileTypes, file.type) == -1) + { return } + + var reader = new FileReader; + reader.onload = operation(cm, function () { + var content = reader.result; + if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = ""; } + text[i] = content; + if (++read == n) { + pos = clipPos(cm.doc, pos); + var change = {from: pos, to: pos, + text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), + origin: "paste"}; + makeChange(cm.doc, change); + setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); + } + }); + reader.readAsText(file); + }; + for (var i = 0; i < n; ++i) { loadFile(files[i], i); } + } else { // Normal drop + // Don't do a replace if the drop happened inside of the selected text. + if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { + cm.state.draggingText(e); + // Ensure the editor is re-focused + setTimeout(function () { return cm.display.input.focus(); }, 20); + return + } + try { + var text$1 = e.dataTransfer.getData("Text"); + if (text$1) { + var selected; + if (cm.state.draggingText && !cm.state.draggingText.copy) + { selected = cm.listSelections(); } + setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); + if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) + { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } } + cm.replaceSelection(text$1, "around", "paste"); + cm.display.input.focus(); + } + } + catch(e){} + } + } + + function onDragStart(cm, e) { + if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } + + e.dataTransfer.setData("Text", cm.getSelection()); + e.dataTransfer.effectAllowed = "copyMove"; + + // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + if (e.dataTransfer.setDragImage && !safari) { + var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + if (presto) { + img.width = img.height = 1; + cm.display.wrapper.appendChild(img); + // Force a relayout, or Opera won't use our image for some obscure reason + img._top = img.offsetTop; + } + e.dataTransfer.setDragImage(img, 0, 0); + if (presto) { img.parentNode.removeChild(img); } + } + } + + function onDragOver(cm, e) { + var pos = posFromMouse(cm, e); + if (!pos) { return } + var frag = document.createDocumentFragment(); + drawSelectionCursor(cm, pos, frag); + if (!cm.display.dragCursor) { + cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); + cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); + } + removeChildrenAndAdd(cm.display.dragCursor, frag); + } + + function clearDragCursor(cm) { + if (cm.display.dragCursor) { + cm.display.lineSpace.removeChild(cm.display.dragCursor); + cm.display.dragCursor = null; + } + } + + // These must be handled carefully, because naively registering a + // handler for each editor will cause the editors to never be + // garbage collected. + + function forEachCodeMirror(f) { + if (!document.getElementsByClassName) { return } + var byClass = document.getElementsByClassName("CodeMirror"), editors = []; + for (var i = 0; i < byClass.length; i++) { + var cm = byClass[i].CodeMirror; + if (cm) { editors.push(cm); } + } + if (editors.length) { editors[0].operation(function () { + for (var i = 0; i < editors.length; i++) { f(editors[i]); } + }); } + } + + var globalsRegistered = false; + function ensureGlobalHandlers() { + if (globalsRegistered) { return } + registerGlobalHandlers(); + globalsRegistered = true; + } + function registerGlobalHandlers() { + // When the window resizes, we need to refresh active editors. + var resizeTimer; + on(window, "resize", function () { + if (resizeTimer == null) { resizeTimer = setTimeout(function () { + resizeTimer = null; + forEachCodeMirror(onResize); + }, 100); } + }); + // When the window loses focus, we want to show the editor as blurred + on(window, "blur", function () { return forEachCodeMirror(onBlur); }); + } + // Called when the window resizes + function onResize(cm) { + var d = cm.display; + // Might be a text scaling operation, clear size caches. + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + d.scrollbarsClipped = false; + cm.setSize(); + } + + var keyNames = { + 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", + 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock", + 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", + 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" + }; + + // Number keys + for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); } + // Alphabetic keys + for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); } + // Function keys + for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; } + + var keyMap = {}; + + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", + "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", + "Esc": "singleSelection" + }; + // Note that the save and find-related commands aren't defined by + // default. User code or addons can define them. Unknown commands + // are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", + "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", + "fallthrough": "basic" + }; + // Very basic readline/emacs-style bindings, which are standard on Mac. + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", + "Ctrl-O": "openLine" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", + "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", + "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", + "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", + "fallthrough": ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + + // KEYMAP DISPATCH + + function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/); + name = parts[parts.length - 1]; + var alt, ctrl, shift, cmd; + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i]; + if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; } + else if (/^a(lt)?$/i.test(mod)) { alt = true; } + else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; } + else if (/^s(hift)?$/i.test(mod)) { shift = true; } + else { throw new Error("Unrecognized modifier name: " + mod) } + } + if (alt) { name = "Alt-" + name; } + if (ctrl) { name = "Ctrl-" + name; } + if (cmd) { name = "Cmd-" + name; } + if (shift) { name = "Shift-" + name; } + return name + } + + // This is a kludge to keep keymaps mostly working as raw objects + // (backwards compatibility) while at the same time support features + // like normalization and multi-stroke key bindings. It compiles a + // new normalized keymap, and then updates the old object to reflect + // this. + function normalizeKeyMap(keymap) { + var copy = {}; + for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { + var value = keymap[keyname]; + if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } + if (value == "...") { delete keymap[keyname]; continue } + + var keys = map(keyname.split(" "), normalizeKeyName); + for (var i = 0; i < keys.length; i++) { + var val = (void 0), name = (void 0); + if (i == keys.length - 1) { + name = keys.join(" "); + val = value; + } else { + name = keys.slice(0, i + 1).join(" "); + val = "..."; + } + var prev = copy[name]; + if (!prev) { copy[name] = val; } + else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } + } + delete keymap[keyname]; + } } + for (var prop in copy) { keymap[prop] = copy[prop]; } + return keymap + } + + function lookupKey(key, map$$1, handle, context) { + map$$1 = getKeyMap(map$$1); + var found = map$$1.call ? map$$1.call(key, context) : map$$1[key]; + if (found === false) { return "nothing" } + if (found === "...") { return "multi" } + if (found != null && handle(found)) { return "handled" } + + if (map$$1.fallthrough) { + if (Object.prototype.toString.call(map$$1.fallthrough) != "[object Array]") + { return lookupKey(key, map$$1.fallthrough, handle, context) } + for (var i = 0; i < map$$1.fallthrough.length; i++) { + var result = lookupKey(key, map$$1.fallthrough[i], handle, context); + if (result) { return result } + } + } + } + + // Modifier key presses don't count as 'real' key presses for the + // purpose of keymap fallthrough. + function isModifierKey(value) { + var name = typeof value == "string" ? value : keyNames[value.keyCode]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" + } + + function addModifierNames(name, event, noShift) { + var base = name; + if (event.altKey && base != "Alt") { name = "Alt-" + name; } + if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; } + if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name; } + if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; } + return name + } + + // Look up the name of a key as indicated by an event object. + function keyName(event, noShift) { + if (presto && event.keyCode == 34 && event["char"]) { return false } + var name = keyNames[event.keyCode]; + if (name == null || event.altGraphKey) { return false } + // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause, + // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+) + if (event.keyCode == 3 && event.code) { name = event.code; } + return addModifierNames(name, event, noShift) + } + + function getKeyMap(val) { + return typeof val == "string" ? keyMap[val] : val + } + + // Helper for deleting text near the selection(s), used to implement + // backspace, delete, and similar functionality. + function deleteNearSelection(cm, compute) { + var ranges = cm.doc.sel.ranges, kill = []; + // Build up a set of ranges to kill first, merging overlapping + // ranges. + for (var i = 0; i < ranges.length; i++) { + var toKill = compute(ranges[i]); + while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { + var replaced = kill.pop(); + if (cmp(replaced.from, toKill.from) < 0) { + toKill.from = replaced.from; + break + } + } + kill.push(toKill); + } + // Next, remove those actual ranges. + runInOp(cm, function () { + for (var i = kill.length - 1; i >= 0; i--) + { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); } + ensureCursorVisible(cm); + }); + } + + function moveCharLogically(line, ch, dir) { + var target = skipExtendingChars(line.text, ch + dir, dir); + return target < 0 || target > line.text.length ? null : target + } + + function moveLogically(line, start, dir) { + var ch = moveCharLogically(line, start.ch, dir); + return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") + } + + function endOfLine(visually, cm, lineObj, lineNo, dir) { + if (visually) { + var order = getOrder(lineObj, cm.doc.direction); + if (order) { + var part = dir < 0 ? lst(order) : order[0]; + var moveInStorageOrder = (dir < 0) == (part.level == 1); + var sticky = moveInStorageOrder ? "after" : "before"; + var ch; + // With a wrapped rtl chunk (possibly spanning multiple bidi parts), + // it could be that the last bidi part is not on the last visual line, + // since visual lines contain content order-consecutive chunks. + // Thus, in rtl, we are looking for the first (content-order) character + // in the rtl chunk that is on the last line (that is, the same line + // as the last (content-order) character). + if (part.level > 0 || cm.doc.direction == "rtl") { + var prep = prepareMeasureForLine(cm, lineObj); + ch = dir < 0 ? lineObj.text.length - 1 : 0; + var targetTop = measureCharPrepared(cm, prep, ch).top; + ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch); + if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); } + } else { ch = dir < 0 ? part.to : part.from; } + return new Pos(lineNo, ch, sticky) + } + } + return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") + } + + function moveVisually(cm, line, start, dir) { + var bidi = getOrder(line, cm.doc.direction); + if (!bidi) { return moveLogically(line, start, dir) } + if (start.ch >= line.text.length) { + start.ch = line.text.length; + start.sticky = "before"; + } else if (start.ch <= 0) { + start.ch = 0; + start.sticky = "after"; + } + var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos]; + if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { + // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, + // nothing interesting happens. + return moveLogically(line, start, dir) + } + + var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); }; + var prep; + var getWrappedLineExtent = function (ch) { + if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } + prep = prep || prepareMeasureForLine(cm, line); + return wrappedLineExtentChar(cm, line, prep, ch) + }; + var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch); + + if (cm.doc.direction == "rtl" || part.level == 1) { + var moveInStorageOrder = (part.level == 1) == (dir < 0); + var ch = mv(start, moveInStorageOrder ? 1 : -1); + if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { + // Case 2: We move within an rtl part or in an rtl editor on the same visual line + var sticky = moveInStorageOrder ? "before" : "after"; + return new Pos(start.line, ch, sticky) + } + } + + // Case 3: Could not move within this bidi part in this visual line, so leave + // the current bidi part + + var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { + var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder + ? new Pos(start.line, mv(ch, 1), "before") + : new Pos(start.line, ch, "after"); }; + + for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { + var part = bidi[partPos]; + var moveInStorageOrder = (dir > 0) == (part.level != 1); + var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1); + if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } + ch = moveInStorageOrder ? part.from : mv(part.to, -1); + if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } + } + }; + + // Case 3a: Look for other bidi parts on the same visual line + var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent); + if (res) { return res } + + // Case 3b: Look for other bidi parts on the next visual line + var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1); + if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { + res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)); + if (res) { return res } + } + + // Case 4: Nowhere to move + return null + } + + // Commands are parameter-less actions that can be performed on an + // editor, mostly used for keybindings. + var commands = { + selectAll: selectAll, + singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, + killLine: function (cm) { return deleteNearSelection(cm, function (range) { + if (range.empty()) { + var len = getLine(cm.doc, range.head.line).text.length; + if (range.head.ch == len && range.head.line < cm.lastLine()) + { return {from: range.head, to: Pos(range.head.line + 1, 0)} } + else + { return {from: range.head, to: Pos(range.head.line, len)} } + } else { + return {from: range.from(), to: range.to()} + } + }); }, + deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ + from: Pos(range.from().line, 0), + to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) + }); }); }, + delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ + from: Pos(range.from().line, 0), to: range.from() + }); }); }, + delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5; + var leftPos = cm.coordsChar({left: 0, top: top}, "div"); + return {from: leftPos, to: range.from()} + }); }, + delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5; + var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); + return {from: range.from(), to: rightPos } + }); }, + undo: function (cm) { return cm.undo(); }, + redo: function (cm) { return cm.redo(); }, + undoSelection: function (cm) { return cm.undoSelection(); }, + redoSelection: function (cm) { return cm.redoSelection(); }, + goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, + goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, + goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, + {origin: "+move", bias: 1} + ); }, + goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, + {origin: "+move", bias: 1} + ); }, + goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, + {origin: "+move", bias: -1} + ); }, + goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") + }, sel_move); }, + goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + return cm.coordsChar({left: 0, top: top}, "div") + }, sel_move); }, + goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + var pos = cm.coordsChar({left: 0, top: top}, "div"); + if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } + return pos + }, sel_move); }, + goLineUp: function (cm) { return cm.moveV(-1, "line"); }, + goLineDown: function (cm) { return cm.moveV(1, "line"); }, + goPageUp: function (cm) { return cm.moveV(-1, "page"); }, + goPageDown: function (cm) { return cm.moveV(1, "page"); }, + goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, + goCharRight: function (cm) { return cm.moveH(1, "char"); }, + goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, + goColumnRight: function (cm) { return cm.moveH(1, "column"); }, + goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, + goGroupRight: function (cm) { return cm.moveH(1, "group"); }, + goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, + goWordRight: function (cm) { return cm.moveH(1, "word"); }, + delCharBefore: function (cm) { return cm.deleteH(-1, "char"); }, + delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, + delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, + delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, + delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, + delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, + indentAuto: function (cm) { return cm.indentSelection("smart"); }, + indentMore: function (cm) { return cm.indentSelection("add"); }, + indentLess: function (cm) { return cm.indentSelection("subtract"); }, + insertTab: function (cm) { return cm.replaceSelection("\t"); }, + insertSoftTab: function (cm) { + var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].from(); + var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); + spaces.push(spaceStr(tabSize - col % tabSize)); + } + cm.replaceSelections(spaces); + }, + defaultTab: function (cm) { + if (cm.somethingSelected()) { cm.indentSelection("add"); } + else { cm.execCommand("insertTab"); } + }, + // Swap the two chars left and right of each selection's head. + // Move cursor behind the two swapped characters afterwards. + // + // Doesn't consider line feeds a character. + // Doesn't scan more than one line above to find a character. + // Doesn't do anything on an empty line. + // Doesn't do anything with non-empty selections. + transposeChars: function (cm) { return runInOp(cm, function () { + var ranges = cm.listSelections(), newSel = []; + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) { continue } + var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; + if (line) { + if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); } + if (cur.ch > 0) { + cur = new Pos(cur.line, cur.ch + 1); + cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), + Pos(cur.line, cur.ch - 2), cur, "+transpose"); + } else if (cur.line > cm.doc.first) { + var prev = getLine(cm.doc, cur.line - 1).text; + if (prev) { + cur = new Pos(cur.line, 1); + cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + + prev.charAt(prev.length - 1), + Pos(cur.line - 1, prev.length - 1), cur, "+transpose"); + } + } + } + newSel.push(new Range(cur, cur)); + } + cm.setSelections(newSel); + }); }, + newlineAndIndent: function (cm) { return runInOp(cm, function () { + var sels = cm.listSelections(); + for (var i = sels.length - 1; i >= 0; i--) + { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); } + sels = cm.listSelections(); + for (var i$1 = 0; i$1 < sels.length; i$1++) + { cm.indentLine(sels[i$1].from().line, null, true); } + ensureCursorVisible(cm); + }); }, + openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, + toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } + }; + + + function lineStart(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLine(line); + if (visual != line) { lineN = lineNo(visual); } + return endOfLine(true, cm, visual, lineN, 1) + } + function lineEnd(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLineEnd(line); + if (visual != line) { lineN = lineNo(visual); } + return endOfLine(true, cm, line, lineN, -1) + } + function lineStartSmart(cm, pos) { + var start = lineStart(cm, pos.line); + var line = getLine(cm.doc, start.line); + var order = getOrder(line, cm.doc.direction); + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(0, line.text.search(/\S/)); + var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; + return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) + } + return start + } + + // Run a handler that was bound to a key. + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + if (!bound) { return false } + } + // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + cm.display.input.ensurePolled(); + var prevShift = cm.display.shift, done = false; + try { + if (cm.isReadOnly()) { cm.state.suppressEdits = true; } + if (dropShift) { cm.display.shift = false; } + done = bound(cm) != Pass; + } finally { + cm.display.shift = prevShift; + cm.state.suppressEdits = false; + } + return done + } + + function lookupKeyForEditor(cm, name, handle) { + for (var i = 0; i < cm.state.keyMaps.length; i++) { + var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); + if (result) { return result } + } + return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) + || lookupKey(name, cm.options.keyMap, handle, cm) + } + + // Note that, despite the name, this function is also used to check + // for bound mouse clicks. + + var stopSeq = new Delayed; + + function dispatchKey(cm, name, e, handle) { + var seq = cm.state.keySeq; + if (seq) { + if (isModifierKey(name)) { return "handled" } + if (/\'$/.test(name)) + { cm.state.keySeq = null; } + else + { stopSeq.set(50, function () { + if (cm.state.keySeq == seq) { + cm.state.keySeq = null; + cm.display.input.reset(); + } + }); } + if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true } + } + return dispatchKeyInner(cm, name, e, handle) + } + + function dispatchKeyInner(cm, name, e, handle) { + var result = lookupKeyForEditor(cm, name, handle); + + if (result == "multi") + { cm.state.keySeq = name; } + if (result == "handled") + { signalLater(cm, "keyHandled", cm, name, e); } + + if (result == "handled" || result == "multi") { + e_preventDefault(e); + restartBlink(cm); + } + + return !!result + } + + // Handle a key from the keydown event. + function handleKeyBinding(cm, e) { + var name = keyName(e, true); + if (!name) { return false } + + if (e.shiftKey && !cm.state.keySeq) { + // First try to resolve full name (including 'Shift-'). Failing + // that, see if there is a cursor-motion command (starting with + // 'go') bound to the keyname without 'Shift-'. + return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) + || dispatchKey(cm, name, e, function (b) { + if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) + { return doHandleBinding(cm, b) } + }) + } else { + return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) + } + } + + // Handle a key from the keypress event + function handleCharBinding(cm, e, ch) { + return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) + } + + var lastStoppedKey = null; + function onKeyDown(e) { + var cm = this; + cm.curOp.focus = activeElt(); + if (signalDOMEvent(cm, e)) { return } + // IE does strange things with escape. + if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; } + var code = e.keyCode; + cm.display.shift = code == 16 || e.shiftKey; + var handled = handleKeyBinding(cm, e); + if (presto) { + lastStoppedKey = handled ? code : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) + { cm.replaceSelection("", null, "cut"); } + } + + // Turn mouse into crosshair when Alt is held on Mac. + if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) + { showCrossHair(cm); } + } + + function showCrossHair(cm) { + var lineDiv = cm.display.lineDiv; + addClass(lineDiv, "CodeMirror-crosshair"); + + function up(e) { + if (e.keyCode == 18 || !e.altKey) { + rmClass(lineDiv, "CodeMirror-crosshair"); + off(document, "keyup", up); + off(document, "mouseover", up); + } + } + on(document, "keyup", up); + on(document, "mouseover", up); + } + + function onKeyUp(e) { + if (e.keyCode == 16) { this.doc.sel.shift = false; } + signalDOMEvent(this, e); + } + + function onKeyPress(e) { + var cm = this; + if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } + var keyCode = e.keyCode, charCode = e.charCode; + if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} + if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); + // Some browsers fire keypress events for backspace + if (ch == "\x08") { return } + if (handleCharBinding(cm, e, ch)) { return } + cm.display.input.onKeyPress(e); + } + + var DOUBLECLICK_DELAY = 400; + + var PastClick = function(time, pos, button) { + this.time = time; + this.pos = pos; + this.button = button; + }; + + PastClick.prototype.compare = function (time, pos, button) { + return this.time + DOUBLECLICK_DELAY > time && + cmp(pos, this.pos) == 0 && button == this.button + }; + + var lastClick, lastDoubleClick; + function clickRepeat(pos, button) { + var now = +new Date; + if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { + lastClick = lastDoubleClick = null; + return "triple" + } else if (lastClick && lastClick.compare(now, pos, button)) { + lastDoubleClick = new PastClick(now, pos, button); + lastClick = null; + return "double" + } else { + lastClick = new PastClick(now, pos, button); + lastDoubleClick = null; + return "single" + } + } + + // A mouse down can be a single click, double click, triple click, + // start of selection drag, start of text drag, new cursor + // (ctrl-click), rectangle drag (alt-drag), or xwin + // middle-click-paste. Or it might be a click on something we should + // not interfere with, such as a scrollbar or widget. + function onMouseDown(e) { + var cm = this, display = cm.display; + if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } + display.input.ensurePolled(); + display.shift = e.shiftKey; + + if (eventInWidget(display, e)) { + if (!webkit) { + // Briefly turn off draggability, to allow widgets to do + // normal dragging things. + display.scroller.draggable = false; + setTimeout(function () { return display.scroller.draggable = true; }, 100); + } + return + } + if (clickInGutter(cm, e)) { return } + var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single"; + window.focus(); + + // #3261: make sure, that we're not starting a second selection + if (button == 1 && cm.state.selectingText) + { cm.state.selectingText(e); } + + if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return } + + if (button == 1) { + if (pos) { leftButtonDown(cm, pos, repeat, e); } + else if (e_target(e) == display.scroller) { e_preventDefault(e); } + } else if (button == 2) { + if (pos) { extendSelection(cm.doc, pos); } + setTimeout(function () { return display.input.focus(); }, 20); + } else if (button == 3) { + if (captureRightClick) { cm.display.input.onContextMenu(e); } + else { delayBlurEvent(cm); } + } + } + + function handleMappedButton(cm, button, pos, repeat, event) { + var name = "Click"; + if (repeat == "double") { name = "Double" + name; } + else if (repeat == "triple") { name = "Triple" + name; } + name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name; + + return dispatchKey(cm, addModifierNames(name, event), event, function (bound) { + if (typeof bound == "string") { bound = commands[bound]; } + if (!bound) { return false } + var done = false; + try { + if (cm.isReadOnly()) { cm.state.suppressEdits = true; } + done = bound(cm, pos) != Pass; + } finally { + cm.state.suppressEdits = false; + } + return done + }) + } + + function configureMouse(cm, repeat, event) { + var option = cm.getOption("configureMouse"); + var value = option ? option(cm, repeat, event) : {}; + if (value.unit == null) { + var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey; + value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line"; + } + if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; } + if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; } + if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); } + return value + } + + function leftButtonDown(cm, pos, repeat, event) { + if (ie) { setTimeout(bind(ensureFocus, cm), 0); } + else { cm.curOp.focus = activeElt(); } + + var behavior = configureMouse(cm, repeat, event); + + var sel = cm.doc.sel, contained; + if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && + repeat == "single" && (contained = sel.contains(pos)) > -1 && + (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && + (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) + { leftButtonStartDrag(cm, event, pos, behavior); } + else + { leftButtonSelect(cm, event, pos, behavior); } + } + + // Start a text drag. When it ends, see if any dragging actually + // happen, and treat as a click if it didn't. + function leftButtonStartDrag(cm, event, pos, behavior) { + var display = cm.display, moved = false; + var dragEnd = operation(cm, function (e) { + if (webkit) { display.scroller.draggable = false; } + cm.state.draggingText = false; + off(display.wrapper.ownerDocument, "mouseup", dragEnd); + off(display.wrapper.ownerDocument, "mousemove", mouseMove); + off(display.scroller, "dragstart", dragStart); + off(display.scroller, "drop", dragEnd); + if (!moved) { + e_preventDefault(e); + if (!behavior.addNew) + { extendSelection(cm.doc, pos, null, null, behavior.extend); } + // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) + if (webkit || ie && ie_version == 9) + { setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus();}, 20); } + else + { display.input.focus(); } + } + }); + var mouseMove = function(e2) { + moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10; + }; + var dragStart = function () { return moved = true; }; + // Let the drag handler handle this. + if (webkit) { display.scroller.draggable = true; } + cm.state.draggingText = dragEnd; + dragEnd.copy = !behavior.moveOnDrag; + // IE's approach to draggable + if (display.scroller.dragDrop) { display.scroller.dragDrop(); } + on(display.wrapper.ownerDocument, "mouseup", dragEnd); + on(display.wrapper.ownerDocument, "mousemove", mouseMove); + on(display.scroller, "dragstart", dragStart); + on(display.scroller, "drop", dragEnd); + + delayBlurEvent(cm); + setTimeout(function () { return display.input.focus(); }, 20); + } + + function rangeForUnit(cm, pos, unit) { + if (unit == "char") { return new Range(pos, pos) } + if (unit == "word") { return cm.findWordAt(pos) } + if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } + var result = unit(cm, pos); + return new Range(result.from, result.to) + } + + // Normal selection, as opposed to text dragging. + function leftButtonSelect(cm, event, start, behavior) { + var display = cm.display, doc = cm.doc; + e_preventDefault(event); + + var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; + if (behavior.addNew && !behavior.extend) { + ourIndex = doc.sel.contains(start); + if (ourIndex > -1) + { ourRange = ranges[ourIndex]; } + else + { ourRange = new Range(start, start); } + } else { + ourRange = doc.sel.primary(); + ourIndex = doc.sel.primIndex; + } + + if (behavior.unit == "rectangle") { + if (!behavior.addNew) { ourRange = new Range(start, start); } + start = posFromMouse(cm, event, true, true); + ourIndex = -1; + } else { + var range$$1 = rangeForUnit(cm, start, behavior.unit); + if (behavior.extend) + { ourRange = extendRange(ourRange, range$$1.anchor, range$$1.head, behavior.extend); } + else + { ourRange = range$$1; } + } + + if (!behavior.addNew) { + ourIndex = 0; + setSelection(doc, new Selection([ourRange], 0), sel_mouse); + startSel = doc.sel; + } else if (ourIndex == -1) { + ourIndex = ranges.length; + setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex), + {scroll: false, origin: "*mouse"}); + } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { + setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), + {scroll: false, origin: "*mouse"}); + startSel = doc.sel; + } else { + replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); + } + + var lastPos = start; + function extendTo(pos) { + if (cmp(lastPos, pos) == 0) { return } + lastPos = pos; + + if (behavior.unit == "rectangle") { + var ranges = [], tabSize = cm.options.tabSize; + var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); + var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); + var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); + for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); + line <= end; line++) { + var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); + if (left == right) + { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); } + else if (text.length > leftPos) + { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); } + } + if (!ranges.length) { ranges.push(new Range(start, start)); } + setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), + {origin: "*mouse", scroll: false}); + cm.scrollIntoView(pos); + } else { + var oldRange = ourRange; + var range$$1 = rangeForUnit(cm, pos, behavior.unit); + var anchor = oldRange.anchor, head; + if (cmp(range$$1.anchor, anchor) > 0) { + head = range$$1.head; + anchor = minPos(oldRange.from(), range$$1.anchor); + } else { + head = range$$1.anchor; + anchor = maxPos(oldRange.to(), range$$1.head); + } + var ranges$1 = startSel.ranges.slice(0); + ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)); + setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse); + } + } + + var editorSize = display.wrapper.getBoundingClientRect(); + // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + var counter = 0; + + function extend(e) { + var curCount = ++counter; + var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle"); + if (!cur) { return } + if (cmp(cur, lastPos) != 0) { + cm.curOp.focus = activeElt(); + extendTo(cur); + var visible = visibleLines(display, doc); + if (cur.line >= visible.to || cur.line < visible.from) + { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); } + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; + if (outside) { setTimeout(operation(cm, function () { + if (counter != curCount) { return } + display.scroller.scrollTop += outside; + extend(e); + }), 50); } + } + } + + function done(e) { + cm.state.selectingText = false; + counter = Infinity; + // If e is null or undefined we interpret this as someone trying + // to explicitly cancel the selection rather than the user + // letting go of the mouse button. + if (e) { + e_preventDefault(e); + display.input.focus(); + } + off(display.wrapper.ownerDocument, "mousemove", move); + off(display.wrapper.ownerDocument, "mouseup", up); + doc.history.lastSelOrigin = null; + } + + var move = operation(cm, function (e) { + if (e.buttons === 0 || !e_button(e)) { done(e); } + else { extend(e); } + }); + var up = operation(cm, done); + cm.state.selectingText = up; + on(display.wrapper.ownerDocument, "mousemove", move); + on(display.wrapper.ownerDocument, "mouseup", up); + } + + // Used when mouse-selecting to adjust the anchor to the proper side + // of a bidi jump depending on the visual position of the head. + function bidiSimplify(cm, range$$1) { + var anchor = range$$1.anchor; + var head = range$$1.head; + var anchorLine = getLine(cm.doc, anchor.line); + if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range$$1 } + var order = getOrder(anchorLine); + if (!order) { return range$$1 } + var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index]; + if (part.from != anchor.ch && part.to != anchor.ch) { return range$$1 } + var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1); + if (boundary == 0 || boundary == order.length) { return range$$1 } + + // Compute the relative visual position of the head compared to the + // anchor (<0 is to the left, >0 to the right) + var leftSide; + if (head.line != anchor.line) { + leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0; + } else { + var headIndex = getBidiPartAt(order, head.ch, head.sticky); + var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1); + if (headIndex == boundary - 1 || headIndex == boundary) + { leftSide = dir < 0; } + else + { leftSide = dir > 0; } + } + + var usePart = order[boundary + (leftSide ? -1 : 0)]; + var from = leftSide == (usePart.level == 1); + var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before"; + return anchor.ch == ch && anchor.sticky == sticky ? range$$1 : new Range(new Pos(anchor.line, ch, sticky), head) + } + + + // Determines whether an event happened in the gutter, and fires the + // handlers for the corresponding event. + function gutterEvent(cm, e, type, prevent) { + var mX, mY; + if (e.touches) { + mX = e.touches[0].clientX; + mY = e.touches[0].clientY; + } else { + try { mX = e.clientX; mY = e.clientY; } + catch(e) { return false } + } + if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } + if (prevent) { e_preventDefault(e); } + + var display = cm.display; + var lineBox = display.lineDiv.getBoundingClientRect(); + + if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } + mY -= lineBox.top - display.viewOffset; + + for (var i = 0; i < cm.display.gutterSpecs.length; ++i) { + var g = display.gutters.childNodes[i]; + if (g && g.getBoundingClientRect().right >= mX) { + var line = lineAtHeight(cm.doc, mY); + var gutter = cm.display.gutterSpecs[i]; + signal(cm, type, cm, line, gutter.className, e); + return e_defaultPrevented(e) + } + } + } + + function clickInGutter(cm, e) { + return gutterEvent(cm, e, "gutterClick", true) + } + + // CONTEXT MENU HANDLING + + // To make the context menu work, we need to briefly unhide the + // textarea (making it as unobtrusive as possible) to let the + // right-click take effect on it. + function onContextMenu(cm, e) { + if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } + if (signalDOMEvent(cm, e, "contextmenu")) { return } + if (!captureRightClick) { cm.display.input.onContextMenu(e); } + } + + function contextMenuInGutter(cm, e) { + if (!hasHandler(cm, "gutterContextMenu")) { return false } + return gutterEvent(cm, e, "gutterContextMenu", false) + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + clearCaches(cm); + } + + var Init = {toString: function(){return "CodeMirror.Init"}}; + + var defaults = {}; + var optionHandlers = {}; + + function defineOptions(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers; + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt; + if (handle) { optionHandlers[name] = + notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; } + } + + CodeMirror.defineOption = option; + + // Passed to option handlers when there is no old value. + CodeMirror.Init = Init; + + // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + option("value", "", function (cm, val) { return cm.setValue(val); }, true); + option("mode", null, function (cm, val) { + cm.doc.modeOption = val; + loadMode(cm); + }, true); + + option("indentUnit", 2, loadMode, true); + option("indentWithTabs", false); + option("smartIndent", true); + option("tabSize", 4, function (cm) { + resetModeState(cm); + clearCaches(cm); + regChange(cm); + }, true); + + option("lineSeparator", null, function (cm, val) { + cm.doc.lineSep = val; + if (!val) { return } + var newBreaks = [], lineNo = cm.doc.first; + cm.doc.iter(function (line) { + for (var pos = 0;;) { + var found = line.text.indexOf(val, pos); + if (found == -1) { break } + pos = found + val.length; + newBreaks.push(Pos(lineNo, found)); + } + lineNo++; + }); + for (var i = newBreaks.length - 1; i >= 0; i--) + { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); } + }); + option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { + cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); + if (old != Init) { cm.refresh(); } + }); + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true); + option("electricChars", true); + option("inputStyle", mobile ? "contenteditable" : "textarea", function () { + throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME + }, true); + option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true); + option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true); + option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true); + option("rtlMoveVisually", !windows); + option("wholeLineUpdateBefore", true); + + option("theme", "default", function (cm) { + themeChanged(cm); + updateGutters(cm); + }, true); + option("keyMap", "default", function (cm, val, old) { + var next = getKeyMap(val); + var prev = old != Init && getKeyMap(old); + if (prev && prev.detach) { prev.detach(cm, next); } + if (next.attach) { next.attach(cm, prev || null); } + }); + option("extraKeys", null); + option("configureMouse", null); + + option("lineWrapping", false, wrappingChanged, true); + option("gutters", [], function (cm, val) { + cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers); + updateGutters(cm); + }, true); + option("fixedGutter", true, function (cm, val) { + cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; + cm.refresh(); + }, true); + option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true); + option("scrollbarStyle", "native", function (cm) { + initScrollbars(cm); + updateScrollbars(cm); + cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); + cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); + }, true); + option("lineNumbers", false, function (cm, val) { + cm.display.gutterSpecs = getGutters(cm.options.gutters, val); + updateGutters(cm); + }, true); + option("firstLineNumber", 1, updateGutters, true); + option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true); + option("showCursorWhenSelecting", false, updateSelection, true); + + option("resetSelectionOnContextMenu", true); + option("lineWiseCopyCut", true); + option("pasteLinesPerSelection", true); + option("selectionsMayTouch", false); + + option("readOnly", false, function (cm, val) { + if (val == "nocursor") { + onBlur(cm); + cm.display.input.blur(); + } + cm.display.input.readOnlyChanged(val); + }); + option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true); + option("dragDrop", true, dragDropChanged); + option("allowDropFileTypes", null); + + option("cursorBlinkRate", 530); + option("cursorScrollMargin", 0); + option("cursorHeight", 1, updateSelection, true); + option("singleCursorHeightPerLine", true, updateSelection, true); + option("workTime", 100); + option("workDelay", 100); + option("flattenSpans", true, resetModeState, true); + option("addModeClass", false, resetModeState, true); + option("pollInterval", 100); + option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }); + option("historyEventDelay", 1250); + option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true); + option("maxHighlightLength", 10000, resetModeState, true); + option("moveInputWithCursor", true, function (cm, val) { + if (!val) { cm.display.input.resetPosition(); } + }); + + option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }); + option("autofocus", null); + option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true); + option("phrases", null); + } + + function dragDropChanged(cm, value, old) { + var wasOn = old && old != Init; + if (!value != !wasOn) { + var funcs = cm.display.dragFunctions; + var toggle = value ? on : off; + toggle(cm.display.scroller, "dragstart", funcs.start); + toggle(cm.display.scroller, "dragenter", funcs.enter); + toggle(cm.display.scroller, "dragover", funcs.over); + toggle(cm.display.scroller, "dragleave", funcs.leave); + toggle(cm.display.scroller, "drop", funcs.drop); + } + } + + function wrappingChanged(cm) { + if (cm.options.lineWrapping) { + addClass(cm.display.wrapper, "CodeMirror-wrap"); + cm.display.sizer.style.minWidth = ""; + cm.display.sizerWidth = null; + } else { + rmClass(cm.display.wrapper, "CodeMirror-wrap"); + findMaxLine(cm); + } + estimateLineHeights(cm); + regChange(cm); + clearCaches(cm); + setTimeout(function () { return updateScrollbars(cm); }, 100); + } + + // A CodeMirror instance represents an editor. This is the object + // that user code is usually dealing with. + + function CodeMirror(place, options) { + var this$1 = this; + + if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } + + this.options = options = options ? copyObj(options) : {}; + // Determine effective options based on given values and defaults. + copyObj(defaults, options, false); + + var doc = options.value; + if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); } + else if (options.mode) { doc.modeOption = options.mode; } + this.doc = doc; + + var input = new CodeMirror.inputStyles[options.inputStyle](this); + var display = this.display = new Display(place, doc, input, options); + display.wrapper.CodeMirror = this; + themeChanged(this); + if (options.lineWrapping) + { this.display.wrapper.className += " CodeMirror-wrap"; } + initScrollbars(this); + + this.state = { + keyMaps: [], // stores maps added by addKeyMap + overlays: [], // highlighting overlays, as added by addOverlay + modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info + overwrite: false, + delayingBlurEvent: false, + focused: false, + suppressEdits: false, // used to disable editing during key handlers when in readOnly mode + pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll + selectingText: false, + draggingText: false, + highlight: new Delayed(), // stores highlight worker timeout + keySeq: null, // Unfinished key sequence + specialChars: null + }; + + if (options.autofocus && !mobile) { display.input.focus(); } + + // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); } + + registerEventHandlers(this); + ensureGlobalHandlers(); + + startOperation(this); + this.curOp.forceUpdate = true; + attachDoc(this, doc); + + if ((options.autofocus && !mobile) || this.hasFocus()) + { setTimeout(bind(onFocus, this), 20); } + else + { onBlur(this); } + + for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) + { optionHandlers[opt](this$1, options[opt], Init); } } + maybeUpdateLineNumberWidth(this); + if (options.finishInit) { options.finishInit(this); } + for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1); } + endOperation(this); + // Suppress optimizelegibility in Webkit, since it breaks text + // measuring on line wrapping boundaries. + if (webkit && options.lineWrapping && + getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") + { display.lineDiv.style.textRendering = "auto"; } + } + + // The default configuration options. + CodeMirror.defaults = defaults; + // Functions to run when options are changed. + CodeMirror.optionHandlers = optionHandlers; + + // Attach the necessary event handlers when initializing the editor + function registerEventHandlers(cm) { + var d = cm.display; + on(d.scroller, "mousedown", operation(cm, onMouseDown)); + // Older IE's will not fire a second mousedown for a double click + if (ie && ie_version < 11) + { on(d.scroller, "dblclick", operation(cm, function (e) { + if (signalDOMEvent(cm, e)) { return } + var pos = posFromMouse(cm, e); + if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } + e_preventDefault(e); + var word = cm.findWordAt(pos); + extendSelection(cm.doc, word.anchor, word.head); + })); } + else + { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); } + // Some browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for these browsers. + on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }); + + // Used to suppress mouse event handling when a touch happens + var touchFinished, prevTouch = {end: 0}; + function finishTouch() { + if (d.activeTouch) { + touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000); + prevTouch = d.activeTouch; + prevTouch.end = +new Date; + } + } + function isMouseLikeTouchEvent(e) { + if (e.touches.length != 1) { return false } + var touch = e.touches[0]; + return touch.radiusX <= 1 && touch.radiusY <= 1 + } + function farAway(touch, other) { + if (other.left == null) { return true } + var dx = other.left - touch.left, dy = other.top - touch.top; + return dx * dx + dy * dy > 20 * 20 + } + on(d.scroller, "touchstart", function (e) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { + d.input.ensurePolled(); + clearTimeout(touchFinished); + var now = +new Date; + d.activeTouch = {start: now, moved: false, + prev: now - prevTouch.end <= 300 ? prevTouch : null}; + if (e.touches.length == 1) { + d.activeTouch.left = e.touches[0].pageX; + d.activeTouch.top = e.touches[0].pageY; + } + } + }); + on(d.scroller, "touchmove", function () { + if (d.activeTouch) { d.activeTouch.moved = true; } + }); + on(d.scroller, "touchend", function (e) { + var touch = d.activeTouch; + if (touch && !eventInWidget(d, e) && touch.left != null && + !touch.moved && new Date - touch.start < 300) { + var pos = cm.coordsChar(d.activeTouch, "page"), range; + if (!touch.prev || farAway(touch, touch.prev)) // Single tap + { range = new Range(pos, pos); } + else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap + { range = cm.findWordAt(pos); } + else // Triple tap + { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); } + cm.setSelection(range.anchor, range.head); + cm.focus(); + e_preventDefault(e); + } + finishTouch(); + }); + on(d.scroller, "touchcancel", finishTouch); + + // Sync scrolling between fake scrollbars and real scrollable + // area, ensure viewport is updated when scrolling. + on(d.scroller, "scroll", function () { + if (d.scroller.clientHeight) { + updateScrollTop(cm, d.scroller.scrollTop); + setScrollLeft(cm, d.scroller.scrollLeft, true); + signal(cm, "scroll", cm); + } + }); + + // Listen to wheel events in order to try and update the viewport on time. + on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }); + on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }); + + // Prevent wrapper from ever scrolling + on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); + + d.dragFunctions = { + enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }}, + over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, + start: function (e) { return onDragStart(cm, e); }, + drop: operation(cm, onDrop), + leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }} + }; + + var inp = d.input.getField(); + on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }); + on(inp, "keydown", operation(cm, onKeyDown)); + on(inp, "keypress", operation(cm, onKeyPress)); + on(inp, "focus", function (e) { return onFocus(cm, e); }); + on(inp, "blur", function (e) { return onBlur(cm, e); }); + } + + var initHooks = []; + CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }; + + // Indent the given line. The how parameter can be "smart", + // "add"/null, "subtract", or "prev". When aggressive is false + // (typically set to true for forced single-line indents), empty + // lines are not indented, and places where the mode returns Pass + // are left alone. + function indentLine(cm, n, how, aggressive) { + var doc = cm.doc, state; + if (how == null) { how = "add"; } + if (how == "smart") { + // Fall back to "prev" when the mode doesn't have an indentation + // method. + if (!doc.mode.indent) { how = "prev"; } + else { state = getContextBefore(cm, n).state; } + } + + var tabSize = cm.options.tabSize; + var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); + if (line.stateAfter) { line.stateAfter = null; } + var curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (!aggressive && !/\S/.test(line.text)) { + indentation = 0; + how = "not"; + } else if (how == "smart") { + indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + if (indentation == Pass || indentation > 150) { + if (!aggressive) { return } + how = "prev"; + } + } + if (how == "prev") { + if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); } + else { indentation = 0; } + } else if (how == "add") { + indentation = curSpace + cm.options.indentUnit; + } else if (how == "subtract") { + indentation = curSpace - cm.options.indentUnit; + } else if (typeof how == "number") { + indentation = curSpace + how; + } + indentation = Math.max(0, indentation); + + var indentString = "", pos = 0; + if (cm.options.indentWithTabs) + { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} } + if (pos < indentation) { indentString += spaceStr(indentation - pos); } + + if (indentString != curSpaceString) { + replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + line.stateAfter = null; + return true + } else { + // Ensure that, if the cursor was in the whitespace at the start + // of the line, it is moved to the end of that space. + for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { + var range = doc.sel.ranges[i$1]; + if (range.head.line == n && range.head.ch < curSpaceString.length) { + var pos$1 = Pos(n, curSpaceString.length); + replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)); + break + } + } + } + } + + // This will be set to a {lineWise: bool, text: [string]} object, so + // that, when pasting, we know what kind of selections the copied + // text was made out of. + var lastCopied = null; + + function setLastCopied(newLastCopied) { + lastCopied = newLastCopied; + } + + function applyTextInput(cm, inserted, deleted, sel, origin) { + var doc = cm.doc; + cm.display.shift = false; + if (!sel) { sel = doc.sel; } + + var recent = +new Date - 200; + var paste = origin == "paste" || cm.state.pasteIncoming > recent; + var textLines = splitLinesAuto(inserted), multiPaste = null; + // When pasting N lines into N selections, insert one line per selection + if (paste && sel.ranges.length > 1) { + if (lastCopied && lastCopied.text.join("\n") == inserted) { + if (sel.ranges.length % lastCopied.text.length == 0) { + multiPaste = []; + for (var i = 0; i < lastCopied.text.length; i++) + { multiPaste.push(doc.splitLines(lastCopied.text[i])); } + } + } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) { + multiPaste = map(textLines, function (l) { return [l]; }); + } + } + + var updateInput = cm.curOp.updateInput; + // Normal behavior is to insert the new text into every selection + for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { + var range$$1 = sel.ranges[i$1]; + var from = range$$1.from(), to = range$$1.to(); + if (range$$1.empty()) { + if (deleted && deleted > 0) // Handle deletion + { from = Pos(from.line, from.ch - deleted); } + else if (cm.state.overwrite && !paste) // Handle overwrite + { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); } + else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) + { from = to = Pos(from.line, 0); } + } + var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, + origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")}; + makeChange(cm.doc, changeEvent); + signalLater(cm, "inputRead", cm, changeEvent); + } + if (inserted && !paste) + { triggerElectric(cm, inserted); } + + ensureCursorVisible(cm); + if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; } + cm.curOp.typing = true; + cm.state.pasteIncoming = cm.state.cutIncoming = -1; + } + + function handlePaste(e, cm) { + var pasted = e.clipboardData && e.clipboardData.getData("Text"); + if (pasted) { + e.preventDefault(); + if (!cm.isReadOnly() && !cm.options.disableInput) + { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); } + return true + } + } + + function triggerElectric(cm, inserted) { + // When an 'electric' character is inserted, immediately trigger a reindent + if (!cm.options.electricChars || !cm.options.smartIndent) { return } + var sel = cm.doc.sel; + + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range$$1 = sel.ranges[i]; + if (range$$1.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range$$1.head.line)) { continue } + var mode = cm.getModeAt(range$$1.head); + var indented = false; + if (mode.electricChars) { + for (var j = 0; j < mode.electricChars.length; j++) + { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { + indented = indentLine(cm, range$$1.head.line, "smart"); + break + } } + } else if (mode.electricInput) { + if (mode.electricInput.test(getLine(cm.doc, range$$1.head.line).text.slice(0, range$$1.head.ch))) + { indented = indentLine(cm, range$$1.head.line, "smart"); } + } + if (indented) { signalLater(cm, "electricInput", cm, range$$1.head.line); } + } + } + + function copyableRanges(cm) { + var text = [], ranges = []; + for (var i = 0; i < cm.doc.sel.ranges.length; i++) { + var line = cm.doc.sel.ranges[i].head.line; + var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; + ranges.push(lineRange); + text.push(cm.getRange(lineRange.anchor, lineRange.head)); + } + return {text: text, ranges: ranges} + } + + function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) { + field.setAttribute("autocorrect", autocorrect ? "" : "off"); + field.setAttribute("autocapitalize", autocapitalize ? "" : "off"); + field.setAttribute("spellcheck", !!spellcheck); + } + + function hiddenTextarea() { + var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"); + var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); + // The textarea is kept positioned near the cursor to prevent the + // fact that it'll be scrolled into view on input from scrolling + // our fake cursor out of view. On webkit, when wrap=off, paste is + // very slow. So make the area wide instead. + if (webkit) { te.style.width = "1000px"; } + else { te.setAttribute("wrap", "off"); } + // If border: 0; -- iOS fails to open keyboard (issue #1287) + if (ios) { te.style.border = "1px solid black"; } + disableBrowserMagic(te); + return div + } + + // The publicly visible API. Note that methodOp(f) means + // 'wrap f in an operation, performed on its `this` parameter'. + + // This is not the complete set of editor methods. Most of the + // methods defined on the Doc type are also injected into + // CodeMirror.prototype, for backwards compatibility and + // convenience. + + function addEditorMethods(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers; + + var helpers = CodeMirror.helpers = {}; + + CodeMirror.prototype = { + constructor: CodeMirror, + focus: function(){window.focus(); this.display.input.focus();}, + + setOption: function(option, value) { + var options = this.options, old = options[option]; + if (options[option] == value && option != "mode") { return } + options[option] = value; + if (optionHandlers.hasOwnProperty(option)) + { operation(this, optionHandlers[option])(this, value, old); } + signal(this, "optionChange", this, option); + }, + + getOption: function(option) {return this.options[option]}, + getDoc: function() {return this.doc}, + + addKeyMap: function(map$$1, bottom) { + this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map$$1)); + }, + removeKeyMap: function(map$$1) { + var maps = this.state.keyMaps; + for (var i = 0; i < maps.length; ++i) + { if (maps[i] == map$$1 || maps[i].name == map$$1) { + maps.splice(i, 1); + return true + } } + }, + + addOverlay: methodOp(function(spec, options) { + var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); + if (mode.startState) { throw new Error("Overlays may not be stateful.") } + insertSorted(this.state.overlays, + {mode: mode, modeSpec: spec, opaque: options && options.opaque, + priority: (options && options.priority) || 0}, + function (overlay) { return overlay.priority; }); + this.state.modeGen++; + regChange(this); + }), + removeOverlay: methodOp(function(spec) { + var this$1 = this; + + var overlays = this.state.overlays; + for (var i = 0; i < overlays.length; ++i) { + var cur = overlays[i].modeSpec; + if (cur == spec || typeof spec == "string" && cur.name == spec) { + overlays.splice(i, 1); + this$1.state.modeGen++; + regChange(this$1); + return + } + } + }), + + indentLine: methodOp(function(n, dir, aggressive) { + if (typeof dir != "string" && typeof dir != "number") { + if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; } + else { dir = dir ? "add" : "subtract"; } + } + if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); } + }), + indentSelection: methodOp(function(how) { + var this$1 = this; + + var ranges = this.doc.sel.ranges, end = -1; + for (var i = 0; i < ranges.length; i++) { + var range$$1 = ranges[i]; + if (!range$$1.empty()) { + var from = range$$1.from(), to = range$$1.to(); + var start = Math.max(end, from.line); + end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; + for (var j = start; j < end; ++j) + { indentLine(this$1, j, how); } + var newRanges = this$1.doc.sel.ranges; + if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) + { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); } + } else if (range$$1.head.line > end) { + indentLine(this$1, range$$1.head.line, how, true); + end = range$$1.head.line; + if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1); } + } + } + }), + + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(pos, precise) { + return takeToken(this, pos, precise) + }, + + getLineTokens: function(line, precise) { + return takeToken(this, Pos(line), precise, true) + }, + + getTokenTypeAt: function(pos) { + pos = clipPos(this.doc, pos); + var styles = getLineStyles(this, getLine(this.doc, pos.line)); + var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; + var type; + if (ch == 0) { type = styles[2]; } + else { for (;;) { + var mid = (before + after) >> 1; + if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; } + else if (styles[mid * 2 + 1] < ch) { before = mid + 1; } + else { type = styles[mid * 2 + 2]; break } + } } + var cut = type ? type.indexOf("overlay ") : -1; + return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) + }, + + getModeAt: function(pos) { + var mode = this.doc.mode; + if (!mode.innerMode) { return mode } + return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode + }, + + getHelper: function(pos, type) { + return this.getHelpers(pos, type)[0] + }, + + getHelpers: function(pos, type) { + var this$1 = this; + + var found = []; + if (!helpers.hasOwnProperty(type)) { return found } + var help = helpers[type], mode = this.getModeAt(pos); + if (typeof mode[type] == "string") { + if (help[mode[type]]) { found.push(help[mode[type]]); } + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]]; + if (val) { found.push(val); } + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]); + } else if (help[mode.name]) { + found.push(help[mode.name]); + } + for (var i$1 = 0; i$1 < help._global.length; i$1++) { + var cur = help._global[i$1]; + if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1) + { found.push(cur.val); } + } + return found + }, + + getStateAfter: function(line, precise) { + var doc = this.doc; + line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); + return getContextBefore(this, line + 1, precise).state + }, + + cursorCoords: function(start, mode) { + var pos, range$$1 = this.doc.sel.primary(); + if (start == null) { pos = range$$1.head; } + else if (typeof start == "object") { pos = clipPos(this.doc, start); } + else { pos = start ? range$$1.from() : range$$1.to(); } + return cursorCoords(this, pos, mode || "page") + }, + + charCoords: function(pos, mode) { + return charCoords(this, clipPos(this.doc, pos), mode || "page") + }, + + coordsChar: function(coords, mode) { + coords = fromCoordSystem(this, coords, mode || "page"); + return coordsChar(this, coords.left, coords.top) + }, + + lineAtHeight: function(height, mode) { + height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; + return lineAtHeight(this.doc, height + this.display.viewOffset) + }, + heightAtLine: function(line, mode, includeWidgets) { + var end = false, lineObj; + if (typeof line == "number") { + var last = this.doc.first + this.doc.size - 1; + if (line < this.doc.first) { line = this.doc.first; } + else if (line > last) { line = last; end = true; } + lineObj = getLine(this.doc, line); + } else { + lineObj = line; + } + return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + + (end ? this.doc.height - heightAtLine(lineObj) : 0) + }, + + defaultTextHeight: function() { return textHeight(this.display) }, + defaultCharWidth: function() { return charWidth(this.display) }, + + getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, + + addWidget: function(pos, node, scroll, vert, horiz) { + var display = this.display; + pos = cursorCoords(this, clipPos(this.doc, pos)); + var top = pos.bottom, left = pos.left; + node.style.position = "absolute"; + node.setAttribute("cm-ignore-events", "true"); + this.display.input.setUneditable(node); + display.sizer.appendChild(node); + if (vert == "over") { + top = pos.top; + } else if (vert == "above" || vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); + // Default to positioning above (if specified and possible); otherwise default to positioning below + if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) + { top = pos.top - node.offsetHeight; } + else if (pos.bottom + node.offsetHeight <= vspace) + { top = pos.bottom; } + if (left + node.offsetWidth > hspace) + { left = hspace - node.offsetWidth; } + } + node.style.top = top + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") { left = 0; } + else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; } + node.style.left = left + "px"; + } + if (scroll) + { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); } + }, + + triggerOnKeyDown: methodOp(onKeyDown), + triggerOnKeyPress: methodOp(onKeyPress), + triggerOnKeyUp: onKeyUp, + triggerOnMouseDown: methodOp(onMouseDown), + + execCommand: function(cmd) { + if (commands.hasOwnProperty(cmd)) + { return commands[cmd].call(null, this) } + }, + + triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), + + findPosH: function(from, amount, unit, visually) { + var this$1 = this; + + var dir = 1; + if (amount < 0) { dir = -1; amount = -amount; } + var cur = clipPos(this.doc, from); + for (var i = 0; i < amount; ++i) { + cur = findPosH(this$1.doc, cur, dir, unit, visually); + if (cur.hitSide) { break } + } + return cur + }, + + moveH: methodOp(function(dir, unit) { + var this$1 = this; + + this.extendSelectionsBy(function (range$$1) { + if (this$1.display.shift || this$1.doc.extend || range$$1.empty()) + { return findPosH(this$1.doc, range$$1.head, dir, unit, this$1.options.rtlMoveVisually) } + else + { return dir < 0 ? range$$1.from() : range$$1.to() } + }, sel_move); + }), + + deleteH: methodOp(function(dir, unit) { + var sel = this.doc.sel, doc = this.doc; + if (sel.somethingSelected()) + { doc.replaceSelection("", null, "+delete"); } + else + { deleteNearSelection(this, function (range$$1) { + var other = findPosH(doc, range$$1.head, dir, unit, false); + return dir < 0 ? {from: other, to: range$$1.head} : {from: range$$1.head, to: other} + }); } + }), + + findPosV: function(from, amount, unit, goalColumn) { + var this$1 = this; + + var dir = 1, x = goalColumn; + if (amount < 0) { dir = -1; amount = -amount; } + var cur = clipPos(this.doc, from); + for (var i = 0; i < amount; ++i) { + var coords = cursorCoords(this$1, cur, "div"); + if (x == null) { x = coords.left; } + else { coords.left = x; } + cur = findPosV(this$1, coords, dir, unit); + if (cur.hitSide) { break } + } + return cur + }, + + moveV: methodOp(function(dir, unit) { + var this$1 = this; + + var doc = this.doc, goals = []; + var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected(); + doc.extendSelectionsBy(function (range$$1) { + if (collapse) + { return dir < 0 ? range$$1.from() : range$$1.to() } + var headPos = cursorCoords(this$1, range$$1.head, "div"); + if (range$$1.goalColumn != null) { headPos.left = range$$1.goalColumn; } + goals.push(headPos.left); + var pos = findPosV(this$1, headPos, dir, unit); + if (unit == "page" && range$$1 == doc.sel.primary()) + { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); } + return pos + }, sel_move); + if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) + { doc.sel.ranges[i].goalColumn = goals[i]; } } + }), + + // Find the word at the given position (as returned by coordsChar). + findWordAt: function(pos) { + var doc = this.doc, line = getLine(doc, pos.line).text; + var start = pos.ch, end = pos.ch; + if (line) { + var helper = this.getHelper(pos, "wordChars"); + if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; } + var startChar = line.charAt(start); + var check = isWordChar(startChar, helper) + ? function (ch) { return isWordChar(ch, helper); } + : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } + : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }; + while (start > 0 && check(line.charAt(start - 1))) { --start; } + while (end < line.length && check(line.charAt(end))) { ++end; } + } + return new Range(Pos(pos.line, start), Pos(pos.line, end)) + }, + + toggleOverwrite: function(value) { + if (value != null && value == this.state.overwrite) { return } + if (this.state.overwrite = !this.state.overwrite) + { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); } + else + { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); } + + signal(this, "overwriteToggle", this, this.state.overwrite); + }, + hasFocus: function() { return this.display.input.getField() == activeElt() }, + isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, + + scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }), + getScrollInfo: function() { + var scroller = this.display.scroller; + return {left: scroller.scrollLeft, top: scroller.scrollTop, + height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, + width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, + clientHeight: displayHeight(this), clientWidth: displayWidth(this)} + }, + + scrollIntoView: methodOp(function(range$$1, margin) { + if (range$$1 == null) { + range$$1 = {from: this.doc.sel.primary().head, to: null}; + if (margin == null) { margin = this.options.cursorScrollMargin; } + } else if (typeof range$$1 == "number") { + range$$1 = {from: Pos(range$$1, 0), to: null}; + } else if (range$$1.from == null) { + range$$1 = {from: range$$1, to: null}; + } + if (!range$$1.to) { range$$1.to = range$$1.from; } + range$$1.margin = margin || 0; + + if (range$$1.from.line != null) { + scrollToRange(this, range$$1); + } else { + scrollToCoordsRange(this, range$$1.from, range$$1.to, range$$1.margin); + } + }), + + setSize: methodOp(function(width, height) { + var this$1 = this; + + var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }; + if (width != null) { this.display.wrapper.style.width = interpret(width); } + if (height != null) { this.display.wrapper.style.height = interpret(height); } + if (this.options.lineWrapping) { clearLineMeasurementCache(this); } + var lineNo$$1 = this.display.viewFrom; + this.doc.iter(lineNo$$1, this.display.viewTo, function (line) { + if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) + { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo$$1, "widget"); break } } } + ++lineNo$$1; + }); + this.curOp.forceUpdate = true; + signal(this, "refresh", this); + }), + + operation: function(f){return runInOp(this, f)}, + startOperation: function(){return startOperation(this)}, + endOperation: function(){return endOperation(this)}, + + refresh: methodOp(function() { + var oldHeight = this.display.cachedTextHeight; + regChange(this); + this.curOp.forceUpdate = true; + clearCaches(this); + scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); + updateGutterSpace(this.display); + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) + { estimateLineHeights(this); } + signal(this, "refresh", this); + }), + + swapDoc: methodOp(function(doc) { + var old = this.doc; + old.cm = null; + // Cancel the current text selection if any (#5821) + if (this.state.selectingText) { this.state.selectingText(); } + attachDoc(this, doc); + clearCaches(this); + this.display.input.reset(); + scrollToCoords(this, doc.scrollLeft, doc.scrollTop); + this.curOp.forceScroll = true; + signalLater(this, "swapDoc", this, old); + return old + }), + + phrase: function(phraseText) { + var phrases = this.options.phrases; + return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText + }, + + getInputField: function(){return this.display.input.getField()}, + getWrapperElement: function(){return this.display.wrapper}, + getScrollerElement: function(){return this.display.scroller}, + getGutterElement: function(){return this.display.gutters} + }; + eventMixin(CodeMirror); + + CodeMirror.registerHelper = function(type, name, value) { + if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; } + helpers[type][name] = value; + }; + CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value); + helpers[type]._global.push({pred: predicate, val: value}); + }; + } + + // Used for horizontal relative motion. Dir is -1 or 1 (left or + // right), unit can be "char", "column" (like char, but doesn't + // cross line boundaries), "word" (across next word), or "group" (to + // the start of next group of word or non-word-non-whitespace + // chars). The visually param controls whether, in right-to-left + // text, direction 1 means to move towards the next index in the + // string, or towards the character to the right of the current + // position. The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosH(doc, pos, dir, unit, visually) { + var oldPos = pos; + var origDir = dir; + var lineObj = getLine(doc, pos.line); + function findNextLine() { + var l = pos.line + dir; + if (l < doc.first || l >= doc.first + doc.size) { return false } + pos = new Pos(l, pos.ch, pos.sticky); + return lineObj = getLine(doc, l) + } + function moveOnce(boundToLine) { + var next; + if (visually) { + next = moveVisually(doc.cm, lineObj, pos, dir); + } else { + next = moveLogically(lineObj, pos, dir); + } + if (next == null) { + if (!boundToLine && findNextLine()) + { pos = endOfLine(visually, doc.cm, lineObj, pos.line, dir); } + else + { return false } + } else { + pos = next; + } + return true + } + + if (unit == "char") { + moveOnce(); + } else if (unit == "column") { + moveOnce(true); + } else if (unit == "word" || unit == "group") { + var sawType = null, group = unit == "group"; + var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); + for (var first = true;; first = false) { + if (dir < 0 && !moveOnce(!first)) { break } + var cur = lineObj.text.charAt(pos.ch) || "\n"; + var type = isWordChar(cur, helper) ? "w" + : group && cur == "\n" ? "n" + : !group || /\s/.test(cur) ? null + : "p"; + if (group && !first && !type) { type = "s"; } + if (sawType && sawType != type) { + if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";} + break + } + + if (type) { sawType = type; } + if (dir > 0 && !moveOnce(!first)) { break } + } + } + var result = skipAtomic(doc, pos, oldPos, origDir, true); + if (equalCursorPos(oldPos, result)) { result.hitSide = true; } + return result + } + + // For relative vertical movement. Dir may be -1 or 1. Unit can be + // "page" or "line". The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosV(cm, pos, dir, unit) { + var doc = cm.doc, x = pos.left, y; + if (unit == "page") { + var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); + var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3); + y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount; + + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3; + } + var target; + for (;;) { + target = coordsChar(cm, x, y); + if (!target.outside) { break } + if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } + y += dir * 5; + } + return target + } + + // CONTENTEDITABLE INPUT STYLE + + var ContentEditableInput = function(cm) { + this.cm = cm; + this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; + this.polling = new Delayed(); + this.composing = null; + this.gracePeriod = false; + this.readDOMTimeout = null; + }; + + ContentEditableInput.prototype.init = function (display) { + var this$1 = this; + + var input = this, cm = input.cm; + var div = input.div = display.lineDiv; + disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); + + on(div, "paste", function (e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + // IE doesn't fire input events, so we schedule a read for the pasted content in this way + if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); } + }); + + on(div, "compositionstart", function (e) { + this$1.composing = {data: e.data, done: false}; + }); + on(div, "compositionupdate", function (e) { + if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; } + }); + on(div, "compositionend", function (e) { + if (this$1.composing) { + if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); } + this$1.composing.done = true; + } + }); + + on(div, "touchstart", function () { return input.forceCompositionEnd(); }); + + on(div, "input", function () { + if (!this$1.composing) { this$1.readFromDOMSoon(); } + }); + + function onCopyCut(e) { + if (signalDOMEvent(cm, e)) { return } + if (cm.somethingSelected()) { + setLastCopied({lineWise: false, text: cm.getSelections()}); + if (e.type == "cut") { cm.replaceSelection("", null, "cut"); } + } else if (!cm.options.lineWiseCopyCut) { + return + } else { + var ranges = copyableRanges(cm); + setLastCopied({lineWise: true, text: ranges.text}); + if (e.type == "cut") { + cm.operation(function () { + cm.setSelections(ranges.ranges, 0, sel_dontScroll); + cm.replaceSelection("", null, "cut"); + }); + } + } + if (e.clipboardData) { + e.clipboardData.clearData(); + var content = lastCopied.text.join("\n"); + // iOS exposes the clipboard API, but seems to discard content inserted into it + e.clipboardData.setData("Text", content); + if (e.clipboardData.getData("Text") == content) { + e.preventDefault(); + return + } + } + // Old-fashioned briefly-focus-a-textarea hack + var kludge = hiddenTextarea(), te = kludge.firstChild; + cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); + te.value = lastCopied.text.join("\n"); + var hadFocus = document.activeElement; + selectInput(te); + setTimeout(function () { + cm.display.lineSpace.removeChild(kludge); + hadFocus.focus(); + if (hadFocus == div) { input.showPrimarySelection(); } + }, 50); + } + on(div, "copy", onCopyCut); + on(div, "cut", onCopyCut); + }; + + ContentEditableInput.prototype.prepareSelection = function () { + var result = prepareSelection(this.cm, false); + result.focus = this.cm.state.focused; + return result + }; + + ContentEditableInput.prototype.showSelection = function (info, takeFocus) { + if (!info || !this.cm.display.view.length) { return } + if (info.focus || takeFocus) { this.showPrimarySelection(); } + this.showMultipleSelections(info); + }; + + ContentEditableInput.prototype.getSelection = function () { + return this.cm.display.wrapper.ownerDocument.getSelection() + }; + + ContentEditableInput.prototype.showPrimarySelection = function () { + var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary(); + var from = prim.from(), to = prim.to(); + + if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) { + sel.removeAllRanges(); + return + } + + var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset); + if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && + cmp(minPos(curAnchor, curFocus), from) == 0 && + cmp(maxPos(curAnchor, curFocus), to) == 0) + { return } + + var view = cm.display.view; + var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) || + {node: view[0].measure.map[2], offset: 0}; + var end = to.line < cm.display.viewTo && posToDOM(cm, to); + if (!end) { + var measure = view[view.length - 1].measure; + var map$$1 = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; + end = {node: map$$1[map$$1.length - 1], offset: map$$1[map$$1.length - 2] - map$$1[map$$1.length - 3]}; + } + + if (!start || !end) { + sel.removeAllRanges(); + return + } + + var old = sel.rangeCount && sel.getRangeAt(0), rng; + try { rng = range(start.node, start.offset, end.offset, end.node); } + catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible + if (rng) { + if (!gecko && cm.state.focused) { + sel.collapse(start.node, start.offset); + if (!rng.collapsed) { + sel.removeAllRanges(); + sel.addRange(rng); + } + } else { + sel.removeAllRanges(); + sel.addRange(rng); + } + if (old && sel.anchorNode == null) { sel.addRange(old); } + else if (gecko) { this.startGracePeriod(); } + } + this.rememberSelection(); + }; + + ContentEditableInput.prototype.startGracePeriod = function () { + var this$1 = this; + + clearTimeout(this.gracePeriod); + this.gracePeriod = setTimeout(function () { + this$1.gracePeriod = false; + if (this$1.selectionChanged()) + { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); } + }, 20); + }; + + ContentEditableInput.prototype.showMultipleSelections = function (info) { + removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); + removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); + }; + + ContentEditableInput.prototype.rememberSelection = function () { + var sel = this.getSelection(); + this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; + this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; + }; + + ContentEditableInput.prototype.selectionInEditor = function () { + var sel = this.getSelection(); + if (!sel.rangeCount) { return false } + var node = sel.getRangeAt(0).commonAncestorContainer; + return contains(this.div, node) + }; + + ContentEditableInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor") { + if (!this.selectionInEditor()) + { this.showSelection(this.prepareSelection(), true); } + this.div.focus(); + } + }; + ContentEditableInput.prototype.blur = function () { this.div.blur(); }; + ContentEditableInput.prototype.getField = function () { return this.div }; + + ContentEditableInput.prototype.supportsTouch = function () { return true }; + + ContentEditableInput.prototype.receivedFocus = function () { + var input = this; + if (this.selectionInEditor()) + { this.pollSelection(); } + else + { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); } + + function poll() { + if (input.cm.state.focused) { + input.pollSelection(); + input.polling.set(input.cm.options.pollInterval, poll); + } + } + this.polling.set(this.cm.options.pollInterval, poll); + }; + + ContentEditableInput.prototype.selectionChanged = function () { + var sel = this.getSelection(); + return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || + sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset + }; + + ContentEditableInput.prototype.pollSelection = function () { + if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return } + var sel = this.getSelection(), cm = this.cm; + // On Android Chrome (version 56, at least), backspacing into an + // uneditable block element will put the cursor in that element, + // and then, because it's not editable, hide the virtual keyboard. + // Because Android doesn't allow us to actually detect backspace + // presses in a sane way, this code checks for when that happens + // and simulates a backspace press in this case. + if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) { + this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}); + this.blur(); + this.focus(); + return + } + if (this.composing) { return } + this.rememberSelection(); + var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var head = domToPos(cm, sel.focusNode, sel.focusOffset); + if (anchor && head) { runInOp(cm, function () { + setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); + if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; } + }); } + }; + + ContentEditableInput.prototype.pollContent = function () { + if (this.readDOMTimeout != null) { + clearTimeout(this.readDOMTimeout); + this.readDOMTimeout = null; + } + + var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); + var from = sel.from(), to = sel.to(); + if (from.ch == 0 && from.line > cm.firstLine()) + { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); } + if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) + { to = Pos(to.line + 1, 0); } + if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } + + var fromIndex, fromLine, fromNode; + if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { + fromLine = lineNo(display.view[0].line); + fromNode = display.view[0].node; + } else { + fromLine = lineNo(display.view[fromIndex].line); + fromNode = display.view[fromIndex - 1].node.nextSibling; + } + var toIndex = findViewIndex(cm, to.line); + var toLine, toNode; + if (toIndex == display.view.length - 1) { + toLine = display.viewTo - 1; + toNode = display.lineDiv.lastChild; + } else { + toLine = lineNo(display.view[toIndex + 1].line) - 1; + toNode = display.view[toIndex + 1].node.previousSibling; + } + + if (!fromNode) { return false } + var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); + var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); + while (newText.length > 1 && oldText.length > 1) { + if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } + else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } + else { break } + } + + var cutFront = 0, cutEnd = 0; + var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); + while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) + { ++cutFront; } + var newBot = lst(newText), oldBot = lst(oldText); + var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), + oldBot.length - (oldText.length == 1 ? cutFront : 0)); + while (cutEnd < maxCutEnd && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) + { ++cutEnd; } + // Try to move start of change to start of selection if ambiguous + if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { + while (cutFront && cutFront > from.ch && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { + cutFront--; + cutEnd++; + } + } + + newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, ""); + newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, ""); + + var chFrom = Pos(fromLine, cutFront); + var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); + if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { + replaceRange(cm.doc, newText, chFrom, chTo, "+input"); + return true + } + }; + + ContentEditableInput.prototype.ensurePolled = function () { + this.forceCompositionEnd(); + }; + ContentEditableInput.prototype.reset = function () { + this.forceCompositionEnd(); + }; + ContentEditableInput.prototype.forceCompositionEnd = function () { + if (!this.composing) { return } + clearTimeout(this.readDOMTimeout); + this.composing = null; + this.updateFromDOM(); + this.div.blur(); + this.div.focus(); + }; + ContentEditableInput.prototype.readFromDOMSoon = function () { + var this$1 = this; + + if (this.readDOMTimeout != null) { return } + this.readDOMTimeout = setTimeout(function () { + this$1.readDOMTimeout = null; + if (this$1.composing) { + if (this$1.composing.done) { this$1.composing = null; } + else { return } + } + this$1.updateFromDOM(); + }, 80); + }; + + ContentEditableInput.prototype.updateFromDOM = function () { + var this$1 = this; + + if (this.cm.isReadOnly() || !this.pollContent()) + { runInOp(this.cm, function () { return regChange(this$1.cm); }); } + }; + + ContentEditableInput.prototype.setUneditable = function (node) { + node.contentEditable = "false"; + }; + + ContentEditableInput.prototype.onKeyPress = function (e) { + if (e.charCode == 0 || this.composing) { return } + e.preventDefault(); + if (!this.cm.isReadOnly()) + { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); } + }; + + ContentEditableInput.prototype.readOnlyChanged = function (val) { + this.div.contentEditable = String(val != "nocursor"); + }; + + ContentEditableInput.prototype.onContextMenu = function () {}; + ContentEditableInput.prototype.resetPosition = function () {}; + + ContentEditableInput.prototype.needsContentAttribute = true; + + function posToDOM(cm, pos) { + var view = findViewForLine(cm, pos.line); + if (!view || view.hidden) { return null } + var line = getLine(cm.doc, pos.line); + var info = mapFromLineView(view, line, pos.line); + + var order = getOrder(line, cm.doc.direction), side = "left"; + if (order) { + var partPos = getBidiPartAt(order, pos.ch); + side = partPos % 2 ? "right" : "left"; + } + var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); + result.offset = result.collapse == "right" ? result.end : result.start; + return result + } + + function isInGutter(node) { + for (var scan = node; scan; scan = scan.parentNode) + { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } } + return false + } + + function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } + + function domTextBetween(cm, from, to, fromLine, toLine) { + var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false; + function recognizeMarker(id) { return function (marker) { return marker.id == id; } } + function close() { + if (closing) { + text += lineSep; + if (extraLinebreak) { text += lineSep; } + closing = extraLinebreak = false; + } + } + function addText(str) { + if (str) { + close(); + text += str; + } + } + function walk(node) { + if (node.nodeType == 1) { + var cmText = node.getAttribute("cm-text"); + if (cmText) { + addText(cmText); + return + } + var markerID = node.getAttribute("cm-marker"), range$$1; + if (markerID) { + var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); + if (found.length && (range$$1 = found[0].find(0))) + { addText(getBetween(cm.doc, range$$1.from, range$$1.to).join(lineSep)); } + return + } + if (node.getAttribute("contenteditable") == "false") { return } + var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName); + if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return } + + if (isBlock) { close(); } + for (var i = 0; i < node.childNodes.length; i++) + { walk(node.childNodes[i]); } + + if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; } + if (isBlock) { closing = true; } + } else if (node.nodeType == 3) { + addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " ")); + } + } + for (;;) { + walk(from); + if (from == to) { break } + from = from.nextSibling; + extraLinebreak = false; + } + return text + } + + function domToPos(cm, node, offset) { + var lineNode; + if (node == cm.display.lineDiv) { + lineNode = cm.display.lineDiv.childNodes[offset]; + if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } + node = null; offset = 0; + } else { + for (lineNode = node;; lineNode = lineNode.parentNode) { + if (!lineNode || lineNode == cm.display.lineDiv) { return null } + if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } + } + } + for (var i = 0; i < cm.display.view.length; i++) { + var lineView = cm.display.view[i]; + if (lineView.node == lineNode) + { return locateNodeInLineView(lineView, node, offset) } + } + } + + function locateNodeInLineView(lineView, node, offset) { + var wrapper = lineView.text.firstChild, bad = false; + if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } + if (node == wrapper) { + bad = true; + node = wrapper.childNodes[offset]; + offset = 0; + if (!node) { + var line = lineView.rest ? lst(lineView.rest) : lineView.line; + return badPos(Pos(lineNo(line), line.text.length), bad) + } + } + + var textNode = node.nodeType == 3 ? node : null, topNode = node; + if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { + textNode = node.firstChild; + if (offset) { offset = textNode.nodeValue.length; } + } + while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; } + var measure = lineView.measure, maps = measure.maps; + + function find(textNode, topNode, offset) { + for (var i = -1; i < (maps ? maps.length : 0); i++) { + var map$$1 = i < 0 ? measure.map : maps[i]; + for (var j = 0; j < map$$1.length; j += 3) { + var curNode = map$$1[j + 2]; + if (curNode == textNode || curNode == topNode) { + var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); + var ch = map$$1[j] + offset; + if (offset < 0 || curNode != textNode) { ch = map$$1[j + (offset ? 1 : 0)]; } + return Pos(line, ch) + } + } + } + } + var found = find(textNode, topNode, offset); + if (found) { return badPos(found, bad) } + + // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems + for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { + found = find(after, after.firstChild, 0); + if (found) + { return badPos(Pos(found.line, found.ch - dist), bad) } + else + { dist += after.textContent.length; } + } + for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { + found = find(before, before.firstChild, -1); + if (found) + { return badPos(Pos(found.line, found.ch + dist$1), bad) } + else + { dist$1 += before.textContent.length; } + } + } + + // TEXTAREA INPUT STYLE + + var TextareaInput = function(cm) { + this.cm = cm; + // See input.poll and input.reset + this.prevInput = ""; + + // Flag that indicates whether we expect input to appear real soon + // now (after some event like 'keypress' or 'input') and are + // polling intensively. + this.pollingFast = false; + // Self-resetting timeout for the poller + this.polling = new Delayed(); + // Used to work around IE issue with selection being forgotten when focus moves away from textarea + this.hasSelection = false; + this.composing = null; + }; + + TextareaInput.prototype.init = function (display) { + var this$1 = this; + + var input = this, cm = this.cm; + this.createField(display); + var te = this.textarea; + + display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild); + + // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) + if (ios) { te.style.width = "0px"; } + + on(te, "input", function () { + if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; } + input.poll(); + }); + + on(te, "paste", function (e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + + cm.state.pasteIncoming = +new Date; + input.fastPoll(); + }); + + function prepareCopyCut(e) { + if (signalDOMEvent(cm, e)) { return } + if (cm.somethingSelected()) { + setLastCopied({lineWise: false, text: cm.getSelections()}); + } else if (!cm.options.lineWiseCopyCut) { + return + } else { + var ranges = copyableRanges(cm); + setLastCopied({lineWise: true, text: ranges.text}); + if (e.type == "cut") { + cm.setSelections(ranges.ranges, null, sel_dontScroll); + } else { + input.prevInput = ""; + te.value = ranges.text.join("\n"); + selectInput(te); + } + } + if (e.type == "cut") { cm.state.cutIncoming = +new Date; } + } + on(te, "cut", prepareCopyCut); + on(te, "copy", prepareCopyCut); + + on(display.scroller, "paste", function (e) { + if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } + if (!te.dispatchEvent) { + cm.state.pasteIncoming = +new Date; + input.focus(); + return + } + + // Pass the `paste` event to the textarea so it's handled by its event listener. + var event = new Event("paste"); + event.clipboardData = e.clipboardData; + te.dispatchEvent(event); + }); + + // Prevent normal selection in the editor (we handle our own) + on(display.lineSpace, "selectstart", function (e) { + if (!eventInWidget(display, e)) { e_preventDefault(e); } + }); + + on(te, "compositionstart", function () { + var start = cm.getCursor("from"); + if (input.composing) { input.composing.range.clear(); } + input.composing = { + start: start, + range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) + }; + }); + on(te, "compositionend", function () { + if (input.composing) { + input.poll(); + input.composing.range.clear(); + input.composing = null; + } + }); + }; + + TextareaInput.prototype.createField = function (_display) { + // Wraps and hides input textarea + this.wrapper = hiddenTextarea(); + // The semihidden textarea that is focused when the editor is + // focused, and receives input. + this.textarea = this.wrapper.firstChild; + }; + + TextareaInput.prototype.prepareSelection = function () { + // Redraw the selection and/or cursor + var cm = this.cm, display = cm.display, doc = cm.doc; + var result = prepareSelection(cm); + + // Move the hidden textarea near the cursor to prevent scrolling artifacts + if (cm.options.moveInputWithCursor) { + var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); + var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); + result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)); + result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)); + } + + return result + }; + + TextareaInput.prototype.showSelection = function (drawn) { + var cm = this.cm, display = cm.display; + removeChildrenAndAdd(display.cursorDiv, drawn.cursors); + removeChildrenAndAdd(display.selectionDiv, drawn.selection); + if (drawn.teTop != null) { + this.wrapper.style.top = drawn.teTop + "px"; + this.wrapper.style.left = drawn.teLeft + "px"; + } + }; + + // Reset the input to correspond to the selection (or to be empty, + // when not typing and nothing is selected) + TextareaInput.prototype.reset = function (typing) { + if (this.contextMenuPending || this.composing) { return } + var cm = this.cm; + if (cm.somethingSelected()) { + this.prevInput = ""; + var content = cm.getSelection(); + this.textarea.value = content; + if (cm.state.focused) { selectInput(this.textarea); } + if (ie && ie_version >= 9) { this.hasSelection = content; } + } else if (!typing) { + this.prevInput = this.textarea.value = ""; + if (ie && ie_version >= 9) { this.hasSelection = null; } + } + }; + + TextareaInput.prototype.getField = function () { return this.textarea }; + + TextareaInput.prototype.supportsTouch = function () { return false }; + + TextareaInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { + try { this.textarea.focus(); } + catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM + } + }; + + TextareaInput.prototype.blur = function () { this.textarea.blur(); }; + + TextareaInput.prototype.resetPosition = function () { + this.wrapper.style.top = this.wrapper.style.left = 0; + }; + + TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); }; + + // Poll for input changes, using the normal rate of polling. This + // runs as long as the editor is focused. + TextareaInput.prototype.slowPoll = function () { + var this$1 = this; + + if (this.pollingFast) { return } + this.polling.set(this.cm.options.pollInterval, function () { + this$1.poll(); + if (this$1.cm.state.focused) { this$1.slowPoll(); } + }); + }; + + // When an event has just come in that is likely to add or change + // something in the input textarea, we poll faster, to ensure that + // the change appears on the screen quickly. + TextareaInput.prototype.fastPoll = function () { + var missed = false, input = this; + input.pollingFast = true; + function p() { + var changed = input.poll(); + if (!changed && !missed) {missed = true; input.polling.set(60, p);} + else {input.pollingFast = false; input.slowPoll();} + } + input.polling.set(20, p); + }; + + // Read input from the textarea, and update the document to match. + // When something is selected, it is present in the textarea, and + // selected (unless it is huge, in which case a placeholder is + // used). When nothing is selected, the cursor sits after previously + // seen text (can be empty), which is stored in prevInput (we must + // not reset the textarea when typing, because that breaks IME). + TextareaInput.prototype.poll = function () { + var this$1 = this; + + var cm = this.cm, input = this.textarea, prevInput = this.prevInput; + // Since this is called a *lot*, try to bail out as cheaply as + // possible when it is clear that nothing happened. hasSelection + // will be the case when there is a lot of text in the textarea, + // in which case reading its value would be expensive. + if (this.contextMenuPending || !cm.state.focused || + (hasSelection(input) && !prevInput && !this.composing) || + cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) + { return false } + + var text = input.value; + // If nothing changed, bail. + if (text == prevInput && !cm.somethingSelected()) { return false } + // Work around nonsensical selection resetting in IE9/10, and + // inexplicable appearance of private area unicode characters on + // some key combos in Mac (#2689). + if (ie && ie_version >= 9 && this.hasSelection === text || + mac && /[\uf700-\uf7ff]/.test(text)) { + cm.display.input.reset(); + return false + } + + if (cm.doc.sel == cm.display.selForContextMenu) { + var first = text.charCodeAt(0); + if (first == 0x200b && !prevInput) { prevInput = "\u200b"; } + if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } + } + // Find the part of the input that is actually new + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; } + + runInOp(cm, function () { + applyTextInput(cm, text.slice(same), prevInput.length - same, + null, this$1.composing ? "*compose" : null); + + // Don't leave long text in the textarea, since it makes further polling slow + if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; } + else { this$1.prevInput = text; } + + if (this$1.composing) { + this$1.composing.range.clear(); + this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), + {className: "CodeMirror-composing"}); + } + }); + return true + }; + + TextareaInput.prototype.ensurePolled = function () { + if (this.pollingFast && this.poll()) { this.pollingFast = false; } + }; + + TextareaInput.prototype.onKeyPress = function () { + if (ie && ie_version >= 9) { this.hasSelection = null; } + this.fastPoll(); + }; + + TextareaInput.prototype.onContextMenu = function (e) { + var input = this, cm = input.cm, display = cm.display, te = input.textarea; + if (input.contextMenuPending) { input.contextMenuPending(); } + var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; + if (!pos || presto) { return } // Opera is difficult. + + // Reset the current text selection only if the click is done outside of the selection + // and 'resetSelectionOnContextMenu' option is true. + var reset = cm.options.resetSelectionOnContextMenu; + if (reset && cm.doc.sel.contains(pos) == -1) + { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); } + + var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; + var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect(); + input.wrapper.style.cssText = "position: static"; + te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + var oldScrollY; + if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712) + display.input.focus(); + if (webkit) { window.scrollTo(null, oldScrollY); } + display.input.reset(); + // Adds "Select all" to context menu in FF + if (!cm.somethingSelected()) { te.value = input.prevInput = " "; } + input.contextMenuPending = rehide; + display.selForContextMenu = cm.doc.sel; + clearTimeout(display.detectingSelectAll); + + // Select-all will be greyed out if there's nothing to select, so + // this adds a zero-width space so that we can later check whether + // it got selected. + function prepareSelectAllHack() { + if (te.selectionStart != null) { + var selected = cm.somethingSelected(); + var extval = "\u200b" + (selected ? te.value : ""); + te.value = "\u21da"; // Used to catch context-menu undo + te.value = extval; + input.prevInput = selected ? "" : "\u200b"; + te.selectionStart = 1; te.selectionEnd = extval.length; + // Re-set this, in case some other handler touched the + // selection in the meantime. + display.selForContextMenu = cm.doc.sel; + } + } + function rehide() { + if (input.contextMenuPending != rehide) { return } + input.contextMenuPending = false; + input.wrapper.style.cssText = oldWrapperCSS; + te.style.cssText = oldCSS; + if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); } + + // Try to detect the user choosing select-all + if (te.selectionStart != null) { + if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); } + var i = 0, poll = function () { + if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && + te.selectionEnd > 0 && input.prevInput == "\u200b") { + operation(cm, selectAll)(cm); + } else if (i++ < 10) { + display.detectingSelectAll = setTimeout(poll, 500); + } else { + display.selForContextMenu = null; + display.input.reset(); + } + }; + display.detectingSelectAll = setTimeout(poll, 200); + } + } + + if (ie && ie_version >= 9) { prepareSelectAllHack(); } + if (captureRightClick) { + e_stop(e); + var mouseup = function () { + off(window, "mouseup", mouseup); + setTimeout(rehide, 20); + }; + on(window, "mouseup", mouseup); + } else { + setTimeout(rehide, 50); + } + }; + + TextareaInput.prototype.readOnlyChanged = function (val) { + if (!val) { this.reset(); } + this.textarea.disabled = val == "nocursor"; + }; + + TextareaInput.prototype.setUneditable = function () {}; + + TextareaInput.prototype.needsContentAttribute = false; + + function fromTextArea(textarea, options) { + options = options ? copyObj(options) : {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabIndex) + { options.tabindex = textarea.tabIndex; } + if (!options.placeholder && textarea.placeholder) + { options.placeholder = textarea.placeholder; } + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = activeElt(); + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() {textarea.value = cm.getValue();} + + var realSubmit; + if (textarea.form) { + on(textarea.form, "submit", save); + // Deplorable hack to make the submit method do the right thing. + if (!options.leaveSubmitMethodAlone) { + var form = textarea.form; + realSubmit = form.submit; + try { + var wrappedSubmit = form.submit = function () { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } catch(e) {} + } + } + + options.finishInit = function (cm) { + cm.save = save; + cm.getTextArea = function () { return textarea; }; + cm.toTextArea = function () { + cm.toTextArea = isNaN; // Prevent this from being ran twice + save(); + textarea.parentNode.removeChild(cm.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + off(textarea.form, "submit", save); + if (typeof textarea.form.submit == "function") + { textarea.form.submit = realSubmit; } + } + }; + }; + + textarea.style.display = "none"; + var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, + options); + return cm + } + + function addLegacyProps(CodeMirror) { + CodeMirror.off = off; + CodeMirror.on = on; + CodeMirror.wheelEventPixels = wheelEventPixels; + CodeMirror.Doc = Doc; + CodeMirror.splitLines = splitLinesAuto; + CodeMirror.countColumn = countColumn; + CodeMirror.findColumn = findColumn; + CodeMirror.isWordChar = isWordCharBasic; + CodeMirror.Pass = Pass; + CodeMirror.signal = signal; + CodeMirror.Line = Line; + CodeMirror.changeEnd = changeEnd; + CodeMirror.scrollbarModel = scrollbarModel; + CodeMirror.Pos = Pos; + CodeMirror.cmpPos = cmp; + CodeMirror.modes = modes; + CodeMirror.mimeModes = mimeModes; + CodeMirror.resolveMode = resolveMode; + CodeMirror.getMode = getMode; + CodeMirror.modeExtensions = modeExtensions; + CodeMirror.extendMode = extendMode; + CodeMirror.copyState = copyState; + CodeMirror.startState = startState; + CodeMirror.innerMode = innerMode; + CodeMirror.commands = commands; + CodeMirror.keyMap = keyMap; + CodeMirror.keyName = keyName; + CodeMirror.isModifierKey = isModifierKey; + CodeMirror.lookupKey = lookupKey; + CodeMirror.normalizeKeyMap = normalizeKeyMap; + CodeMirror.StringStream = StringStream; + CodeMirror.SharedTextMarker = SharedTextMarker; + CodeMirror.TextMarker = TextMarker; + CodeMirror.LineWidget = LineWidget; + CodeMirror.e_preventDefault = e_preventDefault; + CodeMirror.e_stopPropagation = e_stopPropagation; + CodeMirror.e_stop = e_stop; + CodeMirror.addClass = addClass; + CodeMirror.contains = contains; + CodeMirror.rmClass = rmClass; + CodeMirror.keyNames = keyNames; + } + + // EDITOR CONSTRUCTOR + + defineOptions(CodeMirror); + + addEditorMethods(CodeMirror); + + // Set up methods on CodeMirror's prototype to redirect to the editor's document. + var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); + for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) + { CodeMirror.prototype[prop] = (function(method) { + return function() {return method.apply(this.doc, arguments)} + })(Doc.prototype[prop]); } } + + eventMixin(Doc); + CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + CodeMirror.defineMode = function(name/*, mode, …*/) { + if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; } + defineMode.apply(this, arguments); + }; + + CodeMirror.defineMIME = defineMIME; + + // Minimal default mode. + CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }); + CodeMirror.defineMIME("text/plain", "null"); + + // EXTENSIONS + + CodeMirror.defineExtension = function (name, func) { + CodeMirror.prototype[name] = func; + }; + CodeMirror.defineDocExtension = function (name, func) { + Doc.prototype[name] = func; + }; + + CodeMirror.fromTextArea = fromTextArea; + + addLegacyProps(CodeMirror); + + CodeMirror.version = "5.48.4"; + + return CodeMirror; + +}))); +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://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('shell', function() { + + var words = {}; + function define(style, dict) { + for(var i = 0; i < dict.length; i++) { + words[dict[i]] = style; + } + }; + + var commonAtoms = ["true", "false"]; + var commonKeywords = ["if", "then", "do", "else", "elif", "while", "until", "for", "in", "esac", "fi", + "fin", "fil", "done", "exit", "set", "unset", "export", "function"]; + var commonCommands = ["ab", "awk", "bash", "beep", "cat", "cc", "cd", "chown", "chmod", "chroot", "clear", + "cp", "curl", "cut", "diff", "echo", "find", "gawk", "gcc", "get", "git", "grep", "hg", "kill", "killall", + "ln", "ls", "make", "mkdir", "openssl", "mv", "nc", "nl", "node", "npm", "ping", "ps", "restart", "rm", + "rmdir", "sed", "service", "sh", "shopt", "shred", "source", "sort", "sleep", "ssh", "start", "stop", + "su", "sudo", "svn", "tee", "telnet", "top", "touch", "vi", "vim", "wall", "wc", "wget", "who", "write", + "yes", "zsh"]; + + CodeMirror.registerHelper("hintWords", "shell", commonAtoms.concat(commonKeywords, commonCommands)); + + define('atom', commonAtoms); + define('keyword', commonKeywords); + define('builtin', commonCommands); + + function tokenBase(stream, state) { + if (stream.eatSpace()) return null; + + var sol = stream.sol(); + var ch = stream.next(); + + if (ch === '\\') { + stream.next(); + return null; + } + if (ch === '\'' || ch === '"' || ch === '`') { + state.tokens.unshift(tokenString(ch, ch === "`" ? "quote" : "string")); + return tokenize(stream, state); + } + if (ch === '#') { + if (sol && stream.eat('!')) { + stream.skipToEnd(); + return 'meta'; // 'comment'? + } + stream.skipToEnd(); + return 'comment'; + } + if (ch === '$') { + state.tokens.unshift(tokenDollar); + return tokenize(stream, state); + } + if (ch === '+' || ch === '=') { + return 'operator'; + } + if (ch === '-') { + stream.eat('-'); + stream.eatWhile(/\w/); + return 'attribute'; + } + if (/\d/.test(ch)) { + stream.eatWhile(/\d/); + if(stream.eol() || !/\w/.test(stream.peek())) { + return 'number'; + } + } + stream.eatWhile(/[\w-]/); + var cur = stream.current(); + if (stream.peek() === '=' && /\w+/.test(cur)) return 'def'; + return words.hasOwnProperty(cur) ? words[cur] : null; + } + + function tokenString(quote, style) { + var close = quote == "(" ? ")" : quote == "{" ? "}" : quote + return function(stream, state) { + var next, escaped = false; + while ((next = stream.next()) != null) { + if (next === close && !escaped) { + state.tokens.shift(); + break; + } else if (next === '$' && !escaped && quote !== "'" && stream.peek() != close) { + escaped = true; + stream.backUp(1); + state.tokens.unshift(tokenDollar); + break; + } else if (!escaped && quote !== close && next === quote) { + state.tokens.unshift(tokenString(quote, style)) + return tokenize(stream, state) + } else if (!escaped && /['"]/.test(next) && !/['"]/.test(quote)) { + state.tokens.unshift(tokenStringStart(next, "string")); + stream.backUp(1); + break; + } + escaped = !escaped && next === '\\'; + } + return style; + }; + }; + + function tokenStringStart(quote, style) { + return function(stream, state) { + state.tokens[0] = tokenString(quote, style) + stream.next() + return tokenize(stream, state) + } + } + + var tokenDollar = function(stream, state) { + if (state.tokens.length > 1) stream.eat('$'); + var ch = stream.next() + if (/['"({]/.test(ch)) { + state.tokens[0] = tokenString(ch, ch == "(" ? "quote" : ch == "{" ? "def" : "string"); + return tokenize(stream, state); + } + if (!/\d/.test(ch)) stream.eatWhile(/\w/); + state.tokens.shift(); + return 'def'; + }; + + function tokenize(stream, state) { + return (state.tokens[0] || tokenBase) (stream, state); + }; + + return { + startState: function() {return {tokens:[]};}, + token: function(stream, state) { + return tokenize(stream, state); + }, + closeBrackets: "()[]{}''\"\"``", + lineComment: '#', + fold: "brace" + }; +}); + +CodeMirror.defineMIME('text/x-sh', 'shell'); +// Apache uses a slightly different Media Type for Shell scripts +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +CodeMirror.defineMIME('application/x-sh', 'shell'); + +}); !function(a){a.fn.datepicker.dates["zh-CN"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["周日","周一","周二","周三","周四","周五","周六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今天",monthsTitle:"选择月份",clear:"清除",format:"yyyy-mm-dd",titleFormat:"yyyy年mm月",weekStart:1}}(jQuery); (function( factory ) { if ( typeof define === "function" && define.amd ) { @@ -27762,6 +37679,39 @@ $(document).on('turbolinks:load', function() { if ($('body.admins-mirror-repositories-index-page').length > 0) { } }); +$(document).on('turbolinks:load', function() { + if ($('body.admins-mirror-scripts-edit-page, body.admins-mirror-scripts-update-page, body.admins-mirror-scripts-new-page, body.admins-mirror-scripts-create-page').length > 0) { + var $form = $('form.script-form'); + + // codemirror编辑器 + var scriptEditor = CodeMirror.fromTextArea(document.getElementById('mirror_script_script'), { + lineNumbers: true, + mode: 'shell', + theme: "default", + indentUnit: 4, //代码缩进为一个tab的距离 + matchBrackets: true, + autoRefresh: true, + smartIndent: true,//智能换行 + styleActiveLine: true, + lint: true + }); + scriptEditor.setSize('auto', '600px'); + + $form.validate({ + errorElement: 'span', + errorClass: 'danger text-danger', + rules: { + "mirror_script[script_type]": { + required: true + } + } + }); + + $form.submit(function(e){ + if(!$form.valid()){ e.preventDefault(); } + }); + } +}); $(document).on('turbolinks:load', function() { $('.admin-modal-container').on('show.bs.modal', '.modal.admin-choose-mirror-modal', function(){ var $modal = $('.modal.admin-choose-mirror-modal'); @@ -28402,6 +38352,9 @@ $(document).on('turbolinks:load', function(){ + + + // ******** select2 global config ******** $.fn.select2.defaults.set('theme', 'bootstrap4'); @@ -28427,6 +38380,11 @@ $(document).on('turbolinks:load', function(){ } }); +$(document).on("turbolinks:before-cache", function () { + $('[data-toggle="tooltip"]').tooltip('hide'); + $('[data-toggle="popover"]').popover('hide'); +}); + // var progressBar = new Turbolinks.ProgressBar(); // $(document).on('ajax:send', function(event){ diff --git a/public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js.gz b/public/assets/admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js.gz similarity index 63% rename from public/assets/admin-7859f34e107ec35880c203a6c71fbd0b6b9dfdd007b9b8741db3c5fafb22d7a5.js.gz rename to public/assets/admin-d976e0fe3ffbf1de17a34071e36ce92b8971eb5b78bd885db0dc99c73c4d3773.js.gz index 1f8df17c9ca7aa3bb1d61159429571f41af35bca..310941ffdaa35d506b70c566aa7a248bc9a83f6f 100644 GIT binary patch delta 121407 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

u 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Ⓢ2`m%}0<*b?slgVX56>d9l z8#=RC%*+>nDx4!>@nb|WsSNvREV+Gvgl)ZU%=9h= zU}S1jrxW~0Ts7V%bOHVvwOw(S^@$3x3!Rx+o?&b;s?e;HDzc>RCd1ht@=Pxq(^@Wz zEo;MdjJSEE?KG9)C5bWpf5q~ZJC2LB6Cs#kcdZ-bpvs-*?*q{npBw61^(?kj-8&{M zYIfd1Krp8}0iJEV`%U7k9gQWi|1sgdX41t5b%{GbjFGH@qpB7oxtWC|MVF!v)!?u* z8Wj9&S3=ck;76HcENg1GM{@fw%heⅇg*2nn3F(X6B7w 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 )0ig2BPr6 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

YS=BJ`H?NU}x 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

1#7+Y5p|KtM(PtkBdQ)EYSi_@EJ6TjI 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

ELCa#BZDxmDd#QJ9g1nqorEC}TTHBD<%O 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. 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

4aWyTFfoZ~`E$fIA5fuS6PaF#Y zq<<_9A@J}qdjEM!P5ztoox>{g*ds0lzoeOT^8uI`WsYH2u0O0)=)Whk; z7u3G%>LH8-pYt?O2^hawwTM6x-byS$x6`5YQN4FP@tS|<>(wP@?(knx@4WZ8+*!~A zw&7_7Tmv?S1bJ8kehP8ICg(&hg9JL_qMBkoD`kq zYTD@)U(tUb#c|P@u9h9++qA0YN_&by6e%UU1%H+_?Km_6{TXf5qN0Qx1;kO3C|R;M zgg+4h8vZL1%jA-z+WDc+=mRcSd+e1xjQVnx`+wJWeHYn%2lo+%eGTd*m$* z{$$;iUauF6dI@lTS2YNnSp!~1=&+C3o$9$yja`2(FF2?AWQBK4>_-7&s&cyyISV8X zQ9lwmBl}!0s|xEg9#s?CggCYg>UDOFk7!*&%eq&FN+p&r0w|u>^MlEJG+j5Yb}wLA zsmNrlHd|d5e=~DqC@(sb94N_vaH$8ZdAs6C(2S~VY6aP{AFxMQt<7L{J$Kz$tk2vQ zK^cEt&dU*jK?5Kp8pX%tb&3ut;><4yDLHTyyQjy9R<}SLYX=Xs;B*#>BpSsWF3C+_ zVMJx%p@@KmM2g7HVJyQaqD}~De+i7+BWNxwgL)PZ^q_cFH><$wl|W{flPN|IAX|jn zrlLzGwVvMxn*p`K9esW%r|TF`#|gdEx2AsyV6F{Ii|rg_U0+4A`U^j!Rk<%jK}0ma zKi3oAEHH&>DGhhcwL84`^b9q=S8i!P!$Ezq==vTac)qn&;Fbv+lkO25O*l_hzH_#l^7RvjMI^>TmQ z$Quld({~*^>=>@Y`TYWpoU(#Ko(9Evo0Bzor$IR&(dUh8Ao}vT|9lk{f|L%&2K?Wo zieS&Q{O8TucT*R)I#k%UawHWQe=hAtKW+B^@%1C!1lEeAg8LfwNY(?Fq9_!JMvyPV zrP>tPIwDHNQ_^^@Y4pO7n;Rw>EgOHVbra?V-aSWO-;}l*4sqzrw(1AGZNwx@DG|MJ zNM(~`IU7)~Rbz+o?8JAQW(wfRBS00k@H{bcA@|?w)9t0P2p1RQ%9hfxtn(;r#HFhC zqHY2K%f#?X4L04Dsj8%5+Pt-}#6I!HW1rHrggYvvXdI2{ToF(v{DTf;8Nh#8VSFp5 zi`fSZ`h&s%%ji5Eb2&n_MX^siu^CfrN6i z3IEckxAog+4T^|U+^9Ze8){`iS2-!(_4D0?`Ofad>~wIM#K+T46Yne;x!JN3-3}lw z-9R4(|FFj{-95?6Y^~g~Iq82buBF+M0fUlQ{MM!ul|<+RQE0D!oo^-`C%3hfTL_U6 znTAF*vaJLPJtl#U66P&F-nEU*hDJ8qo7dR(QCf!3$Y$qeJiKmc$a$s_bQp2u(JHs- zMr+3H+)w!?ZFnBc3hiPh4@?W58~A5x1kl_OEXsc;GqGu%9R@(XG}K!Ti*Rr<`q?oO z^+65N<`Zk4^*0StUnhS**qPa5BR(21BW2$*D(&C;3GDjH!ftXga5z#UsO;_ou#vfc zhM730-A@RtTipJj5Ntv5lr+D6PQcnh-tqm``T6gk7(K#w^a!)r+BG#dgdAO`2T=!m zW8XQ$S30Yr-9aI1g~9`DZavUJR(ze(b2LWetQT8Fdn`m+WW0YPMXiVLMmDy%l}*=` zPTK|})!CoS7i;el-O|lwgH2~!pWE4wQ-Co8(rilaH;qus;6$vajx(WxNz5TB$Z#0h za1`nLWJEFtg}$-}xkr&j$Pw!$sUBnQqPw@N*Vtp9dINo{`R_Y&puvY2K=_K?+FdPC zaV}YcO0|re1NML4re;I?8NPWSA^8UfnzbUM8Z1{oRG+9Env6Aw9ijCYq!PDQE{S+! zqN15&oU(}#VmlpR1cOXo2d7cuQ*g3uVNFLW^aCuuwkaK`>bO1_$9^*E>uC5&y=ghlmzf?BjYPAZA^p@eC**J$q9Fl>K9xmwX#m1@e-l&=uegkjNVsVIvjkBw|a8UBlg-> zl}hz)qWhk-Wl-U9xhl6V>05B8q$iU_%Py0qweo*mTJv)75}T8`gHbDUBPCwm8)zwm z+c)dgs#=n>&qlM`1r~hzxDTRqT_rQAP$7dA+evP!w*eF~_6o(w>t6cFwbIdd!2Z5 zuGHk5`EiQZLURFuJuU(`7yUgTPdPJ($C-b5jm0}udjzpEiVXhl7iSmx1^?<7SIcst zU-;iKX$E{fHUPBNWrYEHnOxos&8W9mk1sfO_lT}T>@P2>3 z(Th3Y;sKpERkP~C&<-GvO;?f8Fg{>ciAk8R?7L>W|J#p0wo#4;=bitb75*4j2#M6g z+(eAxUT>ROVva^jD#K9m_K;*m(Kwfo4t-XxMwb!4B^fd9c<9TPwh>+S*+kgO38yx} zUy!lPX5H{yu-xbovl}i0ZI)#7zQ@e9?glfmj92b~WqduP zz?E-V16llX{}Bs(ZdZb>*|H3!4gR|!UdM;#NO+by8@|E)DC;trZ>SH6xQ+LXir&ef zj-baYST6BE-HBb$1T@;ZNwnSERHZv3q7D3`hK)GZANJS{FtTqLE)I9|ucCk8roz{2 zy-o}G4#&C9h1YEaEQ-f5t)D)}W@c&9t2TNG>P41DQp(#j$xR}4J{fLg1W8HO_fyc< z2z+`@eGJp-Dsg?;u?dojA6O-`fD((rOqMj{6G!*a$DjTwJZ zelFB@9~g=Z#CMMy~Cuu_C?(usAHvNM(y z73Y&F1@&+DFC@>xL_Q2NK+A962~;qd{6kE3diJ{|!aO$t0F6n=0*NEm+!I~TA?BaZ+V z(qEcIdxn)M7$3IuTeGreW&q&uZB7&Qh^_)3itb@gr_-3%b8&Jusp~F=2x5m_SZ)Ku zHTjTM32Jo(Qc>cyI)Lft%krCGjGy!6xJi~Y;$~jw3r2?dJn?WYjFW_^c&YkiJ*xVHy*qcLf7Gr zME};|1|GzSAUa06#S;MTJ1H(`1`* zh4oIdobabAg*6@}pPR8%djf&tmu#bBT1S6~_gc!B~ zFy;`uA-a*3k=z2nE)ArJ%nZKp>o@yozXqkUWKOX!@{Y^Mk#$8qGOaRXXmGRM_;r*7U`cipdvni?U8$c{&WNt@DVU2+#C~7fRRM_;w0W= zQYZZclfeDG!`VZ7{SGMgn76XG1&I2uFi?8N6K;<*Qcm4LG0Ww2Qex=0!3h{t0pHuc zfChgHiN8(P;|olMc2zIm7bRY1!2DzM{nIDKS#?={nAA(Yz?iJ=I#mI~ktVZ>0pFI@ z!8xF00{|t;DYq+(m*vI5vYKMTKSIl8;Oz2zC9nf<0n`1Dqt8D_h;)?dWwUxr_cDhT zbgQ1j^KPYaYkZ=EVelV#>^@BXgqZ9_g6hx5r4y=AMxxLlQQ z+=Mjeh?H*KBJ!8Lo*2##g9m+-NhrDr($ko*p53Gdj0?ADGK1`4GGS_@Vv_(P$-U%3siz8ZY(9z*jez)3xfJO&WfBv9xJ zJO@eUc@IsF0+n;_p zJUnp!`HTDi%KdS4{_f-bn|pL`%v5@!G7-g2$9j>#{D^BhmWjWzzfUuEQp{uL7i-BU zs7q_hkKMo#5|fV(#Qu_2m?oGK&*vBh_xNCJKrhYxIwk@7eI3%AUx&W(RfS1st%5-wH0v#iD}rQ%=A@&L6=!=9pKU%Ynga z8z6w~05%&p9~YQUmJ(63A!2{PnXDSRLwXQ_c4aAa^*n`?1<(|R&7Cy3=hY)fc(tdd z^NrgS>-DOeMJQI7+8Bm0Kmv5@THHT0a|IP56UEBu%2soS@xVh`v`4so415~9oi~I! zYvdnQ%3Mb9D97u!b&&65-wZ&Vj&1gS1`$}?hD~>SR-oub@x1=tZ4`f-7X!>|;&>n* z+?1A3%0x*Cqox}W3uy=dhe>tv_m;px`;@{6J1{;L{Fiwzj=bT?aaBkWgZu&{VN4HO z8L0(8&ecF~jjH#t4JZ(_tMUR-8ALVus5Bb98P88RXdhm~DGq|-^JQ^#c!;}4^-m|% zKy@2hrR2A(Wy!7@t$=^VtN?&T9_T1KZvc#{Rp;lfz$xtT$gCY;=4bVXsx$O>Lf<+-x@PKxgT^TptBaKA^n zipv5lqt$$LjY*@c3!=mcg(nTmMuL040z562q+|kERzVfZ426H2uBX^oShfv*-|AhH z*##xo=yu$n9r1pq|8^wTp*zD(esL0_n4(9+Azaxm;9r$vV|FoUmSE@ZKr4=M1nyl- z&WC4Czx?8}{;R|3H!mJfFHisP(}$<+ZL>{1H%c39EnYn9{RHkZfk=b4Qf`R|)!! zVCx?9&#&EE_*cZ1lPOnzf%*d+`;7o8{Yf>QV}IUL*I>EV!ry$U)Z6IQExjn0XRv%Bq>^+23%pz} zpE#<4A-d-V_tbMXSmp@wzIk~4NRky~7sVO9*Xw^GU%RV#v*XUa(uv?%kkized^@f( znoPJ9-1LW!q&a)}lVs1;W~i{&aESnM!B4<*GaOiRht*u`Ejb^>cP`(7cw3uFMB&?B zOzX39+Pq>mu_)@k1r%`l4VLBH?oC(EYC zwwHgn8gMNLUi%fMd;x}b%f&suEJ{c8gJ<=@UNAF29XOZp1f%;Wki!5`c-a!50)wGy z+aL$^xb@tljx)Nrb*W9)7@UO-tf4y{fhMUYzHNY}byGD3YQs24SLGbD-!+%+r8>Wr zO>s6|FPD6H(?bH!+fvNr+WOFy_W;#5oI`)GoPsR7%1@u&da18UPNSzlp))WIGZs8F zi#4MX6KME_)+hO2Aeh()vZOL6j0gA&GF>fyWK~I?z41BW)x(#BG5W2UuQ6ZvpOwqz z(RAYUr|2#p4hR6usouh00`2Ts zLIj`|(tm} zsq~jGxG6_}@g)BOUGC#wp7>uq@xOZF*wX(E6M)n67XHGy`ROPA(Ea;R_#J<~fWmj7 z&!67MS;8@eAD@PigrA>xci+*CL|Q@7$+c>F|g9 z%+Y=PGx^MY@UuNSvR%WcI92ex^EHGQxraj|DV~)J@|}Ta^n2h=kC@+zqz6s9n}>@U zTF)%NbMGGuD**f8L$Lhf%n}dzXEeD)8F<0JAjTke@ek2R@_JS-kv4yG3%>Q76IjMS z*WX~CbnnL16k2+EP9jc;!SIp}74Q~?-@&FbL?47FzC$AdiBhi2ui#!|zJgoZ&~Iph zdo{1FK>2s4kEd7&>N2|@1IpsX#k7L6;?;8E*A+@sK*e=Dr3`c(Nv(tS;8hj!tT$-$ zn2*tm#a|PS>e;NE6F7e}nl~!<+C4wJCK}wK0oY)c2!&G+8a8-ajmkM!K%WR#X#Rfg z2HjKL^GMEo#YL$+F;zQr*OdV$kmk2yHS&SAGsr?BPFF zSCiXmRYkudYa#?+d-hEB8g0|V{)hqQ1SwVg7ZCF{~RTzIr&)khzn?FwQGGFYlRAbWnw&#MD43;VL~H=6iLKW44Zg&4i4p|L!tbHZ7VNs9%ORU* z3(m%-oLfP;V%RfXkQQ8ARB%(=BXdariNzp}=e>7Sd|y=ySO~Ln(YT&AE2qkX^CI30 zG{v&KDk#Y;Yy4e^2)ZgEE(*XE%hlv;;&^}jx(C{g({}uk#5E6`8jFTDnYt zj?>Be%C9AY_JRWpCa-mR)3SE2U8}tEgeh_1gXkH@7Zxywem#!47kwnO0&5{9nrg5? z^>oY~VLLAfr9IAgG(p2&c8xm$(IvvhRgywAKHfyj(UruBnam4c3FnP|4KB;(#npfO znQnLq$b%^1 zAaqJmM4V>hro+{-47#pClZVESXPSS)cip659-5E`&zN8m?oEVo#B*pEgr-t`U~l@j zX7=Tl*u9q^9V);8lR2moBz6bi_i_U8=^T=q!S%^} zI0-4njSFI*b2mC}r)S5(zKjnB?kCu@-wk8M0;}Vt5kmXO6Sz7u59pG~Jc65lm1I?y zcG1|n=hMjoy5&?b zH!4IA^kN`*%)ddcbH97$3pf@#DSO#(Firmr{$})z*|@Wdo_L4H3n~*i)EwhMp}G03 z`s8ldpTo_d#VLVfP;||1^I4Rk0z-={}RQ?O)|)!NCNTc-Mx6{R)PCR@!Gf5biuw! zsCvNp1h4JqRk>7-?HHKnltb_(2TdQHoWUE2$ef84q|X`*9T%F(%nk3-x4(oV&A{gV zhSJa7$AaH0IMgx1yp~IUJ{^Q|oR@?hU{+L4N3KN=*AsU%ajOX8y)c0$*N4Lyl;+U( zS+%@C_k<7Ca#}7H?r$N%fc|^GCD#Ncll&Vsi#yZxfd76Eq{Ceo8l=LJAiXwFZ2%h@9~ygex}$5hedU$8WGHm!s9%F|i*0<$C^f{$kM@RAi<{k0u#xB&~o= zD$wdR4+I2+Cj0`VsLnnyY)5Ad$YclbL47wF_eXM7ESKNa7ZXqfuT}ap6)K7>R4xI; z?WAblPZl299nsc9+H^C))Q7&uKq*cDYX!-QS>s_0;(Cc-10k&QZ)nr_ryoFk|jWm*Ks zP2eP;=X7+z_%S`fQ#_Zp%Ua@O-6*|)Kf9g`3#Jw{2q>F>pnFm#^w1qx>0I)dzV!C+ zoyFOttirEX^|HLEUT|Z&Oaf#3x(ggFx0&Eppu_(u|N3O~{+cH#qLdrZ2w(y}=f zF%rm$>f$(r%vuphfIl<(7zmb^^!YKl-!B1*WpoMq<0APi+zx#Wv!gseM>^HrPGm6- zU)qAvaGTeh>m@$I?em!a#+2-YoRtKF@uEBla!g>o^0Jg9&LzTs7yvo8$44VB-#-qm z%HSn`i@X(q2=u9Cz2rRJT50n%A47PElHc50kT)cGdfC0_2bRU2!`ikVloXM4ZWYaV zrh^)q8@B9p>ehfaGf*$$4OL|Ul~QS;p(*0!vK72HQEFL4H8U!p`oduwNg7+Ne98Xv zvX->eZX8~^2dAqp42j;XH8n`QOWPKdddnn#)G;qBO90yfbX&Dd{;n1 z;nWAAUy5lVCXyd3`#$^{v~hyO_~)`J4#`LLwlz;K)B z2eNEnbalZ`zQF?$hq(JA$9%9Ux&D6(YUQP={|2(0afLbdkeS%uN&Zgo3->p0={5Lc=; z5ZHP)ZzM5P)K%PW7$GGTyv*KH0prl;t4xP;5SBvKtNC zw#fKMlHVrxbdNqgE*_zJ3kt067zWQO6_=lAy%y|P)2jSX2}S7X2*N|=N;?jJ;-#s| z<>>P1{0E;~-ijNN+I>1TCX-?r(=C%%XnD~BBFABo@Uk!cKz@}SL&v$K&GgMlPEr%J z4ZA1}Lw0ia)_|ek+#c{ABfr1I@$z;XdAxs87@#I|Ld$G*+s|VUGP>cN^gQO3yo4Rw zSC<>D>`LnE<*k%`0qh=K%2JenrK#qO=DBrlZ}yB@oo%sJd0iX%8<|$Mb~buR$<_}1LXd#rV7gJ5@GTgImBq`f>-ouBWO55Es7uSLvDaUT*f`svopUhS z=GqA_9?4mNG_35XwlNh>i<&@6u!%I)zH!GZaPEhEGNTpibPO%y7utD$=-Q-~DxIBh zJhK}&eYR(Ix7^@nB=cv-#q*lL!`x;CtYi*2u9M1U{zydtz$7>haU$qoS~U$uID(@; zp4-9O|I8JsmTu-|6}lytb0R`pR$qLB(5?>i`@XvN&N+MH6~o^XA6M_$dK~`bY!f!N z!JshDEXs??(oN749FE<8A)F9!G_lVCDFmLnkN$I9V{}+Ool-&$vGsn3X`@;`+h*+# z#nI>+g?GZEL50c0dI`X0HCH(k#E45(pt+npA#>)^#IYpVAAz7_;fR70MSuxYHuRld z7CTGl>t$3GzVD<+5N{)fGr$gSk}QSC$H70tw_CPy(zDvTL_g(JZkrZ~7y{{fRM zHM%eF8R&ThmlKgr?`?d2T_n zd3fDz7c^6$hAdjNQY z@a0Zi8-kmEw%5;Ar=Z9kKfWk0(%QR!JgF|hrQ521OP@z4ytw{W`9cKp_3P<+Hor{^ zutJ8$ZCa7ikQmqogO^JyF42n$@s8rAfI}IXl#AKdr z=}tnX9FG$s5R-blwye((CEZX0sEjw|*=D6X!hP-hl+t)zpJ(apnFNBPO0ryPC(amR z*KJni87JgY_l^8;Q;5?hPfWc@dIwBCKSg%T^Os^ghLRn*tSW4;}`WVx$8> zQilnJ93sKyiZ1BAPg6rl8Zc;52<&+b@2a7HfDi=fUXnM}c~ybcHjo&^p0la_BPS#Lb(3UDmGxPF z!?oaQjKYmXK!T+2%H^UErcaD0y3rzkD{2p7hv{M)xqWl@XV*NrA!GA^yG~bK)dp8H z`{w?}1OP=_r|$Rg2lz94zOu2D%IQezyZ*9o16oevuB-6Mw)w)YM02KsQ9i^Z+s88= z#?1qHh-uTa85D~BjpK*TDj$Rn{;lGFUi(|>>NeBmRYGCQG!%ySZZc7=v|MS+fpKDQ zcA)D1lig(W%}>)M0>NEf1bPgy^}9rllV&XfCo5y1_%0s&@ucVH7*C!kRTKcek}{or z1gO{B-)-8P0QM`Xh{$%f!K}r>`k-b22EVx;Ak=3{N49g6flQk~<=j%ULlhBz^sP`T zUWB8ziDXn%@+H8Py9qHiW=nJ!)xMi8@}9~CS1!KhKH)#Gtnw8LuKRF9Evc@M2>W0@ zuem@k3d;(S0+jy{T1h3j6(D+Ij9hIz`~$lLB>%tb6<-)qpAPb!imW^;!996Wk!y^d zQ?Dlvw+%t?EFF zAY1{8Fb27=Y6>E?;deDbIzJ?r1DruD-p6D&NysS27@l#6y^k^soCDSuioU-JJwM-C)oH_`(1>=R ziLdJ=C5uGHqYzk{Mq#Mj(Ze@_0$VpkU}lgC=p!)+3sf+RU5GXy6qw%X6l|EA?r(tO z;)Fov`$;*|08tv8SldvST5l>Uap2KRAt<+5OjeZ-DW|-}8s(sWa1&Vj@ZQm7HF{4} zUP0mqcpza+sjWFmp|Oh(8!u7cD)(1kG1$yAe`_%B*oes&yf zl^(JBm$h+NbOw*flL75eAU{9d6&xR`VD&To<&X_?FXN>1Q92JAb@%hb_I!6HMU{{S zHTPf10W#l!xQrElSB@d8RkuC8T9i`M&&JdFoYSemxbGJo4@{${M`uD^uB#m1XKBWC z5;3q-Egb-!tmX~!LwV#&y%Pa|2?;YZ!yO?$sLH}kp*rP-`mS7Y<2#Pbw_J+UEbdNk zsBvR5G-08q?exsin#&XYC_xQ)2nl@EiC|C9&z(C&TL=Ds|I* zW^^a>(R2;%EbbEY#@*ha__~}-CBC11=s`F-g@H5tLGD;I5aKcGU{+JQ8d7CA{7P(f zfy&*B`fe|OXjwdt*bXRIJGDg`5rquJk}-k_!F3R1%9-|X$|-K)(5U?r9cQ&lU`sqU zXK0Nt!j!o8Ul;Y;(}Vx@jwR_Cgu|Q-XvBJ{U1W2^d&bNmIfN4r#+Fh0EkhLs>1LNj zfw~T@igZ!n<(*y?7=L8JIg**a3zLi{K};g>dnVd{!_tHI(QCIQEvhlBp|E$TR37dH zTv~5VQH*{FFBX)t&%L6&El;L?lW9$gm&@t<^oi?*)5#@aGupcwGI&?bs9dPLaFoSw zQvLHowQQipUlvD42(O|6SML8Av-k|?OFuBMpV5EmLT8L1EK+s2*P`c+nC{UR2utI| zP|*B;CH2!un;;zSwdHhjYlm7BD@Bg%^Z z>{_J|m#tB;zZ(e0rgtjF<1$%{X1jjTX9+$(@5*VIG?+Eugs&IvWpEk+FvphDilO6w ziA_Z9>kPd(`Je0N_i9kmA^CzJ7$=R#2Ff0bBcTNqWc6k~`4YtbMp5bUpjwiE!bG)a z5B1<=z}GUJ@CMc*3O$cjmdVoQyB{PRrd?k8r}AT%!TeH#XC;*TR(>PNYN6aL1;Q3S z(RF%Bju`?s)(KY3Ye>xNoj#N7&>( zrT?whXKudW!O$kBbWdJYi>h38GwsHcPJQJ%>GKJP)fLf2%a45|gVdcvA~#LnDhx8C zF-2<+5Icuk7mF!oM=&?Hfe<%;m=I#DeEJ6;^kPql0)c-4Zx-g)a4hAGyftYbPM86NZw%slEhy0!wZDdqi4`9I$JX8 zH^~13B-aBFw9%@>k3(t1LdWE;JL~+dqEp_jb1}06*vO>Bzgs=Duu0WVE0E%w7cOf(JxrU zW%2}WOsXxCkxm_N>NN!fTY<^==MBE@rV@6$K|ekOXtlp(Z@1aKwVr)doxPu|A{c{* z%Sm-Ub^1Cq%jr-!uNNhMA-nfcjfX7WJiG`^IIcAT!uc*FlR2N90+y5S0!~)79PkIG z(LDsGtj{LE)F;$dT6`J7IW8lY0wNFr`6K^5oqyvNtWVjT-Pv1{H}}0vcZvu7*{yJy zfNZ8ZaE5A=*FM!3V>nQP%aDd%RD%Eb^gg65oR#kZRey=Lakx2utL`oUd3jNQ?^??!e)=%Ck=o}v5OLmCIP0^px47->-QY3HN% zSEE{jQ zIeTt$S!}P1fA58Ha{tTz8|D%?cMZJTC2uVK<)XJxCdr^u*Yoqqg8)<3TJ75|a@%CXNZ;&XHi*7M0qWsNqM$0M{2A};ic*B($@-%;dY z%;_8-yhp-+cZld$kim&{Jz#LPn0Uv6A{d=v-|{+zw-_@4ivy#YhSBaz-z2fA5x3co zhF$ZpQZ*RyDy-p)!1P4i4y_nd5}ZkN+0A zaSr%*gIjseo#+paG!;apPAah|r+gi6SHnwBs(c#xxmpsVUgjVI&zU3-qZRhM=4_srRjK$xO*>sZ)PeS!kU zXMvC0g(GvfKThp(#4*0jxN*q{fl?jsTWHIFW}<|4v>dnRC83WEfc5$qk~DP=B>uX*(!voY=uxJ-!a7hWufI&k~zpecDbTG2%`D z3KbU82Hr{?lw{G-zitT7wY5BJI8%j_0Pdf^7Y9XkUw(ixoh|kcUF;t{@Vh@^P}v*1 zpkK59Z}zMuZDOU=+uy&d$XOFDT;j2RN&otUakmlyTI+3F|GYlf>_a~WoNF#HeNZfh z;pY0T6QNECt|4j-%ro-kJ?&1FG!FL9)|SJ|Fyn9&_8XPLLiipP=6n|XV^v#UQM5FA z!&V=Zhk5}KN#xWddI>D6HU%Qlco>Rycm2Wj-RrK@mvq;P_1${C#9sE{FNjt8g+EMT zj9v@&VUO~X)y$w2NBbXY!0~Q>=B2KDEPNv9x{cYqG5dp*e!#&NvK>h4L-eB*eb?%C zs_KL}=CS5aTN|5dvs9EeFP4*8xx5bEqnUm|8GL4Z3(bgmrVj_($U+_~7q{w1;iFAb zLou-$MYbr9L(`LkqhW45d^9X&GE9U?#J|`}Gp#XqfE+}>ppR+@2`x8Dd0yOB9wa?YwaL1l3pug4F7N&vHD>Rr3iSbWkjROEjUq6Lyayq}`(gok9ZY;%GWf3Kg<9q(BvX@wSC#fPx~5?Z6j;3F+g1>L&B9w7SnNB(g5prt$TsSpH}gAACylmX-GM_-I<$I;{j`Fa90hxo&y8!%=U9WKm> z>Cp-pnV>83_=Z=xVPr279LN(IE$d7DQPy=7?=9(9{8xMZB7N42unfHH()n2)_~L)S zmy@1jpF-E8Cf($J03;MzL%s<{V=(k~mX?u9xK(U!-9R)}APdKSVWj7cns+$3;=8Bw zRsF-Hy6OgHK7-?nTJLl$o4!cMVJd4{^crK;vsw*RCY1ze^Jl!00=h{iuVAdp(7(MD zBLnIyMP*>=72(Tn5d$Cj28aPT`c!XY4)OSFR44zv@)z@eJu(`bcJ|uRiW5`dShsMJ zsw#zpR>1iMUPDsN$vFo#1S|(W8Y2I4r)eIv+`6S=0ExW=2WQl`n|O;Qz;fQPV!H!m z4+4uGBqv16(JMF!2Di)a`4~ypBk0u!VKK|x`4SRH1jo09J@4AGJJMIgdgN*_c*5G(W3U^Ld=|=dF zqxJF;=C(d5_V>B=a4&|>NzX=dF50N17_%{ehNS9$kF0aV6=7Wn?~={x-X1rCyN+mM z@F^>HJ`k`4!63k2u(LK@Z61h|ntE^=UkB37z*VQb`O?3@Jg04z;I^9y*Fg$G;3+%t zlMy^q$iL&pEu^E*wfQ$MxgDoX#6g>Fu3xIeZ^Axl&l@ z(2fazf1tN>|Kdnh?&=-e)rcjs{%7LK{U$~FC{KndNC*0FzZFq2B6a$?rmhp_2M@g>vMMcoyS?sy14J+9)?AK z4t(p-`E>mAx}obB)`B>Cb+Lqg7O;4U3?`t*oHIYKXNzK7EhrJOB%fhi8n^#U$T^tU zSfKs@~8i)`r1&tvY0=|6Lw*hF%ULTpifjw1OML3b=g828VrOL>2`J zApbTOHWNAo6;mqpv~&m@v2&uu$rNpJXV1eP9d! zX;Y3(pX3kDUaeMdp#5|cUvWyDzF~N+azdJ>6Gi8M=iW_KSMuo`=!ySRlFJaZoFg^w zVUWC8*v~p-2X>^hFSXfS4In2;Y_*$5MIVHsYV&bY^QB%#zCrtBs6hhUkHg-(Aclzb z)koZnGO;u@w-0f{T3^XmC6k(e{De$uK7k<@ZOhlqYa%S|6UnTW$Ta@ztFVBM)%jD< z7ZnSdjE5{TY1g6s;xQz|nqk6ixA~y%Q!=PTa)`UY2mx|if&*Z~%MQHHj!#n^j7 z*md@ge1U&t*B!d|3Q?gXG^Ap1W&*F~ZnY663)=1IJz%@%`LsqT6z_^o{io3=ph__n1GyoK&!hf8^T7Q_!5|D-Iwa0 zjFbG5+FjwPn)>EQ9-Mf8nsDGc@C^f)uosvBL(b-T3@SUwuNT!QAW`k_Pofl>s^>B* zqsz&3{Jb6`;;oi|7qCh%HqRPN`t0vXIyBOH5V&*oZ3P9r>NERCblRqN*!XqT8PzC> zoA%?ZF$Aefh_Mf72pWPgHyKIXc;q&o2_dr4qnY*Ip=T8Az!$=QI(OfT=Wm|;{Y~-g z$@A}vZ%>~;{_g4XZ}{Dtnu35x(qQmL;S}t3aaAwh_u)`DuShXCqnPQd4q>qWUrG@2bW2S2^uzjxu9)d}du z`UVkN5Gr;5>(`%}o~w#g3M3#VKQv%IDq-&u2Q43V{*>Z>6+W(Nin+SeEVhkGt*{nITB&uY83$`*F_M=TY4aT23;#*3u%ns?Phd z&p!L{+xN78XRXDSXhZtik@dFb?T$e!(frRkcRZ_)b^7E$f}sG0oIc8iEk5)R5rv3W zxZix)Dtm^ILy)SfKe5nx!(wt{cx5PkI7PX-H(QVw2X% z3@+BNfJ)g7!>@za3;eMq-&8A$(EC&Hs{}HpzN^C{?W1s9BP;<(ry`Ku3Bvw&Q;>eC z_lH*SPw4wQ85WSETBDZ`zl$Ys1aR=;CQBhOfA9C(jEPK6MA&iwI?BCHTN zq>%Z4p)f7dayx5BrT-GF>v#HLhkD#MLi>GQm*D@KS zjibabGr0UDBp& zmHl;f!^DiusIrrioH=78$#ML4TlfMX?hyocCUK@1glB~&$~PJDvx0wi;ooyl z;J+Vvak{H`HTCcA?nhSePj?$m+)4@`s4+x?v^`|DclquJ)6tw1_tbUI7QytaqN;Q{DNsPtojh_~qKpM9OGj$h`*b|~7WJ88W>-0$^uc?9BE|O) zRh`QO=}>wJ57d&(D6n8pZ7m8TR*Ro7$Sng)z^l7fb;|jSz20S0tb^_&W$ZwcwGm!( zb#*ZcL1&XTHTy#>fw+>TAn=NR*zPDoFzJz5TymqWpsXL_k@T`jN+N#o$VMo4Cmwt- zylSTtokKj5Wf2stE|}=ETSa0FZIIPZTMCYqK?`N{l#@ z1F%t1t$3ywKf8%adLb16XRzAnE>h36T1SQ>)0BHgi@Si_M=idtX7*;WsiA}7WI<2_ z8X1$mWE6}zCDp0)DNq}tHm7pO!cD;|+L@5}H;E2v5@5(2ZQ7u9FUHnk(Yye3;bw+6 zGsjjer`a_21WQ(|R$elHRLCPPR}P|0tyGOX+j2{o)30a1N{v^$?HE{J>^XW-euJxH ze))*oi9lQ6MZKxD-gXRm30QZh*x`UT8(nEy05*InIt>mP?&@y491ymXi3qmAwjMa-FxbDe+eG$Pd+<_#q08>6X zJ+(|9o_4MI=Yq-yTpV%;v-=_Ma+PrS$x(dGY9~xXU-b)aq0j07Mi+d3Mlqc?4@X&9 zaU{_=A`tuYYH_Jlk3Y8N6H81(^x#@L-pgU)#ieXCfn9TMZEY@lDovA2Uc;4og>%Boq!Z&oIrq5V22dvfQk|LYvunTAWoeM! zeO66wA13%J-g2qy(7gr53=E5KgMnm-7Rw@h#{3QU99vU=xHn5*n1sTOnUWki9ZoIk z2-DXFRggAb05Ycd%~~y-Ah=wh25+*`i0D!wcNXr{TX73f#F1UPQNJKbD>ise%_aa}ZN=sMK0M$RkZ7DlWEP4p# zMngM=TefO{>pGbG8JH?e&_i$k@lajl;(Wu)T9hkQm+UcL5C%D@ z2a&whYE@}<3SpP&Iq(f0rAgoxbS=HhmU&HyUX_)9lUy-`$RN=vCV0?@2b1H)wWIUzW5O9~Ly+%&h?6~#3@Jc1b&u^tIg zIryc2Q69-(aJ?KI-q^X-Fj+0onluJtZ8m7Zb>5v6G*4i;lY_SfQk)V^fwabrG&s5j z{nj+o;ca-6*tWvVa!Z$gXWwn($`CeZ)@X++GLJY8^rROC4hfcJ z7m16ct9936&q%C%M}#ICA_vEzdvQ;jK<3YHnUH!Gbup>eRNAH_tlue$duWqr`fQp$3QBDD3=Ce z3O0^mb`d{-G$hSga8sH*!x9{W71JQy%e&TuiB&5YUyQWu>KMCnnefC_uSyJm>Z3~m z>x$`E^vu#Ww- ze1_&rM6L1gCW|3sO=1Hb^f3p2myiWI)D7cYrFFKdJ+M<;%M}=VyTbHaXw{8_;dAIB zGC72=qIsU}i+ZFZ2i;An)A+JQDoNE6ZIGEB?(j%jX(Do;RVM}Q8?D(4-`c)b*>J+i z@N7}s_RTi!hpk*U-;V0A7hM&A;m9Nr8#7SUsIOKafxW}%zJP#cEeJ4wpm@l9LW=tm zH;XP}kfkNjNe;nm?hM-4Jj#3eiJOpy8R}5@^Bms&^Sy56n^6 z4H5d#H{+#Cg;z*|ckr4Eb$Juu--wShxTdMF&%*viY_G`b3V(K}By)YmAb?Z$*44Zv zgd$=6tyf}TK^8F^1LhxpcQM6G&AMu0!R%ifvAZW2+awW2zqUqlaLS^@$PFmfi`Y(s z^OwAAq8k?ktf;j-XEYIzp=sCT4N%S#j@<$HHiLE>-K-6ky(tm*Na{qqm_xM%b#YtS z+v#`N0Cxeey_1BKn;SL2gS3QnVDB0;CD!o96?U@Gx@S6FqO7KW81p=O2ywmxbcm!0 zSq*>!J~*HQN6jkIUOD*gaGS8m4KyEr%s#tc!uGFpn{Fynsn=z&H_#8mIJX zew)gpMH)Eyvd@h+Fe5j@8F>2>Zmaax@d5?mhxRz_<@07O z6i35!Q4Q{Y8o!5qT~9F16e8DpSHH-Au(&aY8hv-6t0nT-+FEj6Y!SM<9l2*yu!h~> zEI~uHNr&TaHcI!hPjo7?!0L$P_+)6?=~?Q;Rs_4I$BgP?B*<%uhX_2sIyIJ6%TI3T zDDgp2pAH;-Ys%hc{DARmYVAvoqFS)Pc7tMqz*A({O~mgY~wbo-82#Ge2lN}&$& z5^nJB0I6QWOw=^SkjJ-B1=^a*qb~Mi6O9lzDP-BiNTUQ`mxHZoKyH16YQNI?HH+#g zR7_>{5mv~r9c~2_T5WzG9u+%RR!Ro`mIE6*5Lfi%0X{)5TojF&%;1sLbl4NSGk?(& zd`PW-B{K@HWAkv>Wf(EM6K0cxEQ8YrVpka}RY%bpqpYyBW^PVuczQm+u(#kq8^PPF zbhfRD2K8JOwGh#xQh43#W;IJf-pi#r3mK=WB_!e}E2cnvco3PI0gRT+3`NyMT++aQ z>UJ8e0J<2h2UmLply4b~i1bc&vUVfS1htaI2kSeJ9BDFZm2h%=iwm>x)CUpIxvGB{ zt+@?eUa`e%%BYZIaESV5BnMu#;#n|wZjeXYe^j-U1gw>f1QWLzx!FigW;PC#Mu>?1 zM4hFGN8S}q;sjCHb&MXhgc6-}cAFi4o-IJHLa!}?P(bA=dJv&>ZC`PvpqU(i=2b^F zC10-^hb;x8tJ*4uY%ixflW~e}1L_W4gF~&x@n_P#Js4Ne*{U-FnPLuIIyoHWT~uS2 z;KE$c9R@DpC>8HO2u@an}O0@T$e)7Uj)uqa?FF+Z{p|b^EJ*-$Xjc_rs}wf}#Op+#K=x zDa0}K1hmV}&Iv`M&bo_8cx1ORk;^hdt;Wxiv@migDnY7;D`%VWMdYu2f11KLq`G;q zwX5dDtmQLuD_Gau>Z#ULc5cZl3zp2rEV_arncy$baFxS}80e%kP}ytF=4d)>0=zcc z3;e0Ii)+lB&2>e#Y6C}qDJKwYWP4V{eCC~GWd$^JP}!Lc{iWl!2dqI}R9o&y;@GGR zPddFZ>%rzKc@H`DubBJtlDmO8-|~h>Zkj&0JzZPbddB8thgQ16^3SS`TswmdnKhuR zpn;w|b3DyrHhbzMxy(4c`w&4;!`UKh2*#!wn(1IaS2PdTOiG-82J*GG7zR$Gt9Xvr zNRpN?AR36nFpbKN<+KBDVKiU^g{=DVq=`7@v$yEk9$U!acNN3;${&6AcQBzzcvU60cIqUg$ zGR>By$vy3svYzaJ6o9oqLF1M!GJe}WVrxak_7v7)u|*6D*wf%*J;;*VAniPWxxAgz z#9H?hhH)6>S>U}Md{|~<;ojHd5;Rq;hR3FbU{s1d5+gKc|Na z(@D|LL!hY3VA`ML&vAv8jzFwFu>_Lq%&_M}wW_X*x!2>F06H%2FhmaxVx&`_)W!>T zI4~S8Hy|c|SY@zJ#P-}O@?oR);;@ErlBO%ZMmebFKLsUO(YuFJ?+nV;w%m;|TatLW z>YJilUK|BmGTrKMftbl@cqMJ++wm9)M{f8A%q+SScAmo0>oYm-g(kL{Zrlwp=x6;o`Mfc^r?-guo?#&`n-vWRY<|GzOO=2&oReCFh+n z;eZe*h5GoEK7m$NnpLr(Doz-I^l0E{b)Tqg0m+7&4;&K6U%gD3Fe)$q#9#_) zaL9gyUfT;I^HkIrIGo@oi^=gP0&;R$aSebWEXGz8Z$G$JWX9#ic(1~^wD<$DiRw`(={=sA!fP8@r0R02^`2Q zA;)?`q4y@mdIA`pbO4JDc3wQd`cjlikO>-t?PT2&^ck8-9e0F}4!~m_aV7c;S+_@s zu&Ff%2qJ4Jb`$);HRoxRmjIDxoG?gSB6@6p13;lD@@lGeyaclWp`>dB9vEgi5*#+o zg;;&o7F=~}FB@NG%n;{1w|qJ&I7r(0af1K1?jgL?1L~vb__?Nx(Crc|NvCYYQA!EY zFuV&{BhZRddLuseI!2w#yO601u7U=FE=t}6%k63O(9uqjj(duiNHH+I`wB$4@V8Na z14gLU?6`-rI6AYor_=JnLj(cAF-W*|f3P0B4#v-Pcx8BF6owu!Fts6*MlEZBF+9sD zY4tibNs-G=h{-o=#c;!x`v~v!y1JfdxqzaWg7FrAnWC72K$G)aDa!&=z6y# z2TKo(195}srQ)MN;R+-xv54+5T+*t4<4s^LEpoJNM~^6dM|ujZfRLi(E+4m*Lv`Ek zCCklDfwo|G6+^{OdiE|T1l?eW81P`dFloeN?^yYRA8DM?VnJT!40jZg>lX2Dx73~w za~SsRmdn1~bEuO+>WUNqD@S$V7KglddCNq0z!Ou4gVr)qLN`j8dnrteDYe6Y8ahp* zZRznDVG0s-`pEf_*_1NKH9tjH9opX5JzA%OL)OY*aQ}u!jnf-GZX(U^R3pz8qeGx$ zcrW+ObUE%D`1y!^F!&=w*Z#V&bjyz3T6?PJ7SoIGo8vSUrdU68;7sH0j!pV5)24^H;YUr*AVvgl8LLB&Hr+Tcf( z4La(u?e);DN-f$0aJyJf&W`SO)aoIRCrngKCos`q_BJ$eqsWc$j&6eb3CKzl2n@@$ z!);-=UmUD+Cpw93kB-S;YJE)Bx~3j#)|ef1o5rs6g|33f*A*4l>*;~HvrfE0VJQ(FVLWQBKk9DN!pg?40Gup1aact``$_QzJ#G;x~7j7$lCB#dYX;vWsYbLu*6O0(q69+yin&2DiaafoIRB ztP;K6mJ(LP!kw^x$a64)3pGkx)dFA~T53SqPOcT@gvI1bLWf%>I@A^pmRxw>_ALQU$=z5x~ zeSaC-e2p6Ret|Aikdgi zE!oJ*F`TGdDY7dm0JvBQVPZwqZQEK(9pj!ckpoP(UL5 z+}&DcIPQVK&t=gH$F;2$@#ll;n*3Ful{isX$=r_8)F=;03~J=3sLQpILNg0{m9wD6 zL3o0;y%8{f_ET`tExK|!xcL-gWot8D+#>xT9i0L-44sdTD}`|vZ?lv5mWjhx111U2 z{OJ(Y0=4aigJ_75W+SRiSM?IOHtF+8NRSLQ4de{IAtQVapt zlj!Uz{dV@I(y8JRU)->)IxXxbJ(WJDH>RXDjQ-zb*@2G&rv!C4)3Mo;evc&*#f)9a zuJn~t5l+Xc_{NrdI#f_K&E~e({n)&z1Gblck7Jg3K59#jK}qFkcwYh&7^6+e$I^t4 zf|p5BAcb&1&q?|K1l=>F6Pz`b0{@;Tn;}SU%zUZ?o987;KJu26Yn!I2wGC7q5jqh?&FKwzZO6+Qg9F%qbpbf009$_lhBVgm}Fd63|fa2ceXQy|_r$ z8Q7Ru5^ab*{}Q_{!W`iM=P-!gWT*pkK(W}tS0SRi@=z!ipt)dnoJ|VtGRVIBM^>rSlcGMN-NO7NP8%zPyVmc4D6 zfAX79^#$P*!Om#oteck(!Ph)v3eKY{6B9!xdFMkWsoLq@mjQ;v}rQg7-B(< zm=O?R{eH=c*b|U_)GW<+F#(7W0c@AGpC%YDZkQIwI|Z;(#Vv-T;%tE8EM@D!29+&T zL(OCrLdc*CC6pu`xAAyT-SR@M8#9@Ne=q1%=+?RIKsnF0ow0x?gB&(WgIjrqn%GR9 zddj7Zh?4_p&+BU7;dF8i6-^jy6I5H|X{x)al0*(_v;}g@I0I!o$+^vd!B-&Bv9sRo zvMmQX??+%c^1v#(s6NIL&f_1WIjU(uuUZp>wgz$Yx~P?2<9wjFpH7H0pC^yie|0L* zC}H3`OmA$xl3uNPsfx>#IrtHb&b0$)i}YbOzQ#~?+*r(ek?dsCYdBx9TpmbE9El=>X%+fDk7~{vT zr2OtGLZq_|EmYfrEZZ$-zO3rhe@d5o z`jL{jRYc_!CT%s-NF#yJ<%!n@#Tsmfhb?3Hil#GWZ~Peb6sI)SK;ePOF%^pULBGNw za#D9~P$QdYN-2w>1bQZ!veI04Z=yfhFQh+q)3f8y}9QByoEvC#QzWK>?WWrQpcBSVMG17)DH&il8zWZk>b zg-b+^m1G~0SOQu&K`(@3thnJ|giX%K`C>D0HE}*~ftn3Wgs7QbhLzKM4grqUZyuJD zY@pj9vWYrF-oipt$c&6J!w-{U6t-5z7Z&X$wQbm5dSBVzdlPVZf7Y3yc7Q$#+Ara4 zOdp&`$9B-U#xt(!$3}K;`hs}MaDio19`zvlmJhrAX)hxbk$`Wa`ya!gLbe+_x1uMo zCL?iKm3EJi+f`E;yMLL~_yie?e$vaRT_%GPD>!AoAwwfXR(R}iCnbW5T@R|i!u8Wm zg+~oNUnDoTdtnZ?e>G@A!{x)-^*UOsUPAsHBIen!hbzm3(uMy(1OzO%9xq-_E6y@$ zaK%l$j0Agxu?oRrBiJYs`N@25$hF!OhyYX&?9&&>Mj}>DSAPzRu_xrm8K5Fw1e+=c zTjm*SyX=3uSsXbk92!`kcn)#@kPSr(Y#t!)ZZXb36P(9Ue>m!nf0quadz|cg7h?iL zg3B(c?P#I!EBM(FL3(@IhC$nxpvyN~&(!>sj(tUUu#)c$)e*l!upwY;0ehzA>q17C$#=nt03ir;nD!1qtsQ_HK`&m$PS!6DeCdTAwK~>Nhk>+sL(7NO)HWZ zL1+BbghUfd{xN{|p&!9#17zwHXEA+EW3#(i_hK;^qyQ0W?+Sy!|FKJn0$~#*btk}F z2q?prO0iAwJq)P;8u{vR)1DPE%_G83MBH|0f08F0VAS>wpyJd?{;cR4>44G!AV9Q| zDMpaL!%<*QB9tR_?OAuDQ?VdpwR+)|vmLGu9_Uvmkm-)2cUov{bGBww7Z{ifP?>rJ z9Hp50#L8f=|1qJ=em>dENirLVrXyG7U|PY>;@Q|_ng%R7>^LqS-f{W#p@5#%SNTu` zf9V1Kle0Br6+xFCr-fYE=rrwEHv$d)QYT4$U3_vAUE4N@9hs)#lcW{dw&S zwX_yUdE8Pk(RIaKx+-DmEEZoVY{>)sf0^7mbLLgY42qbl*~#MT5SC5XAE&@0h;l?p zyow+x=5mD0p6P~5?mj+;-0c-fRg28q&++AE64{NV zVT2KdjjGVAE0Wq>Z#XGh&117V)mmWTU|n*aSql?hGLXn#Rx_qOs2i{-Iz}(x4|>|` z>CoN)*J?I|D*{IU{vV;WW?sI)&2E?i zTHH~0^`DoKVfQ6Kr!4{omGk>Yk&oF9Dj0K3V-jmOM&JK~(8-K0=vQjy*cnO&nk2+Y{|z;Q6A1n^kBM4EzO$8}4}?zSC?@b@M;L4G zX$4gtrM;ceWJ1T3z_B0EAIwPd5AcW* z*Q%fkWLUl&>xbTM&l_(Vd&8Km7;|z z_!;z$M|vWze__$c!LHl9X)fh<7!WcW zC<=x_&fTb%5(eaYA+5YT^}VlnR-`5exD=DI71QlIIDf&dz`%1K7>k%VG@?i|3m4HZ z51mhoXW734m(CsxiQ|^mN<legazBP1~7AdJr^E-+#a|eO233C7iP~_$rQOS-B2@x^+qwu(6GQYtMMG|?FjI# zLD4ZZe_u#Bm>O}1C|aClg0-gf8w051@^8?PK<6tb0gne`_Fjb z*|KlJv&TNgth^D_3vYrk znl|&|C_y4#pkw=TAJ5jgMe!+r6kOvLFG62^WEn(Y7A;{9Q>99B zw=o9xxRvZoCpyRsBLa!+k&_Oe_rqBc~0jBdOwqwKIMh^7}KqoQ|gpymbnMf?%P-!yQ; z+$^p-cOvq)w|Wn>R#5-IY_O2RF&Zm@H?Aif;IsB>1OM$y_-=0iK?f00aNd`x=QxPxlRbbp!LOk&0k)=q>M0wKn-8i;l$q74BG zd+2}e>gdq)gEedbxN=Zil3FnuFapTI0aHanvZ0%7nbLuv$!g1{SRxF(leRYUtb$D) z)Mxy~uEDy&wX)_*di2zSYLkC1Zv-yI&Iqdy+FDUA&P3``lN!3cf7d!kGa|(V9!RLE zFl!CH{JrKv#ZN6f$uhzhg*Jhc54`to=c5agVvu*m!9*udOP@6kk_N`a{gnR)c zTqmbO*+Ck9Y6~0B8%YaPFpc21o+-wbzXG#-AeT6>c$y-s1xQ|siDGuEoqWu4Rva>s z>?VK-g4JC6H#_M+e@^h|uC+&HEW^9P!KIZPc9!DyATBk6R~+xpK;4MIH*v2HhFwG_ zf0lTtZDx9+fADR`4Gi3Iu)yzR7qs=6@d7bTT1ncEC#R(-#kNc_sgIem4#~!yR`Yr3 zd$F#4C7Q&CsN!s;e0PeGa-4TNQiqKG6qJ7^dCbOBVOBI+U`9)%4Eksc z*ogQIv@TIz%_wENm`=*5xtXNd=T&o`+(0OzL(N$k**@19Y%908Lx_?_!}WLs;hD-1 z+wS6x>o+f}|1Vv+dEx1+my;{kpZnO&Wb@`HuU^(sQqd)v6s{(4fV|IH=xq|93~*(4 z>>F@Qynrawf7b;Pf_+Q=p7K4ao&Ci4(xkOwEle=taNERNUQ&eQ(Av0ByNUs9e@f$K z-cvV-?73{57am+aegzfur5o37=7X%5%Bl$)H8wm#)RN=E6jFNQ_9r)UOjpCfey4h5 z03;o?7Epm6U<>U`@9DSnxw@3!=~UwQ_Q0+{hB*+(f8FA>1LEz!w|L&%a5RFvV}e2W zv3bS9j|M{qiWCObh!}AI9`a=qmQ|g88IKqF^g*yRh>2DL@t*cGjQ^0*rJewnFg8b* z=8x{05SuMMlpyxmOX@Hxq48>Go;^!J!zR2K8g7u|XxI!kP$y|MD0)goU;LH zj)KwSe+7#pJ;AuZ@qy$DPpv>tPOvG)klwMSl35kfP23(YU!+LTlTBe(%%y_ zLv*{UA?mE1)rv?X943jXMLy0;i62CpVOj9ZY!)Eell)egxfuHDj;bk~6w~g0IC)O^ zXo5N(ce9JO=a+}Qh79~}3d}iNf>YLlGgH}1e^ZSqwHRJ3Mu!*G0$*gqMz*GoR2A_} z5VPb)5fm{H*+-wk5zuAHS|&G|N1k#gYZGU`K{1gyKF}cm+RA5l4~K5pPzsJP`hpx ze-&{ub)THLNV2(p$RyMjVbG+eZzoSgePc#MF-Iu|IQrRLwP!LGE9!axx1L0^WtI(4 zVyO<&E_|^k2ZzGK&;ab7|G+2M&)ezk1_f~e( za-RYzla z(UAP$K*j^d{k#z8t5)MkEd|pahYOaMVIz<5b2Ruu;d+Cycwv`kj?=K>8Q*5TPF&Wo zNV8!m<897|yAT*Ky`AAC=q})?0pBoYm~M_V(-Hm<&N)d@l6DL33z)cy!dag_b7oDF zYarnm^)o@nq2$G9OCGV&nUdPhe~6r+I2dN*OL`Z{(i+W^487mi%2gwLCEeQio@CYz z7;Cx_n>=7GfldrxTx4Q=L#V_uFrjOOg*15(m~_F6TFb+yf;2aA$!IX*Cu2oeYJ#3H zNIEX``^-ytsuDk#Yj--P8#WTS!Oa2$b}%GRR%&kK@|m%hIg)h%ubsxMna0&XfFU;vxBwzigGR%3*G6F+Vn_kVv9-3{9*|{WdytN{ z&TT6qjAIM1Nw#{%d#YMPe`<;O)lLdAJIfBtGK%)7Qqb~4GX(vj_<{W0kp@ykij71x zxP*YI;&Dqp$O4mfnXa=Wv6^{2sQfMZBlFrJsYr5eTm4ho{ z5rl7S%a9K={EivEvAl)jc@{ZkiuuqmQIlN zdStE*jqX&%?sgkFf1}XKBIVTv)&wtsR0u?^*|JlL8??vVP;p45z1?{7Q7gb~I588A z2y>8u^|s_77Cw}{3Ze&cwGBoTQ4Q7&|wqF18jHNEC z<4*dF`MYQJdy)IEuuQt=IBB#i^)Xt1wip$6<>Jr^e^26WimT*qD23mF$Y)S4fIYh@ z(wKOYuVXg8lcL3(5WxmVy)4MzP!;8zj9l4qdL(M4y<%JzXn7+_))gP_)9Xl5{$TD= z4&8RrTk6gw3&I^Hr1uMpyW|AVrg5G|dD(iT1e}l&DMgr=>Nxasr6ML??~P%iPW^F_ z_mYeIf9gJ(A-E{&J0Jg03otVj|5kz-GsG_iqhL_&p`be*>O!Ul6E)fC7v0-xTcY@s z%xqxSi-^CdXI15LnwBmkC9IC2swwNHQ($%{b&BGuOK*XYneHWb^6_Mv_D!_gwl3yr z&a8W-)x&AOUmPS;6yT@b2^lf>vI)e=(Oom~e}_i^515r0g*GWub+JBx&^f3d?!xjx z6?uuOWDFmSJ=#ai*HU(<%m>rHq6?)e$J9c_8-+96wQTU&ggEd3j|>-Uq<%`k}4B z)LM~ze?tdu$3iQ0aJB&`Gy~fSh-Nhr`^*2mGjKu{&5%_FmuN<07hs@Gef7e_q zTSQ+k8nSp0%Q|rRx@n2q3`jRLE%t;-bE+^cU$83MQxwo5pe|V5Z{|C|3I>LaMfI@g zCDRe9X$mHVI{~H?w=qumGIQt@+}m&|m>phtJ!8`~T%SU3?2V);IW~^Ei4aMQx;3-L zFb|F-9DR8)ExpmSS8qKnvo77Lf4k%hqKVF^pX0VG8*t`e#F@!KmJQ9~q(g@qDYpXk zxG83+==ZpAMF4CuL<2O1q0DOx$D}7Uq!?Fyf}v|-_$cm)p5~{LvlyP3njqe~m!y6< z(K&Iu!87MUHddE9Dn@X()5Y;4wQ6N0A`9h=YPUhLoKHQ;LJ=BK7HeMUe}Or3#w*%2 z(seXy6GdR~+@nBlmr+l#)^Vm9an5bi(59YV+7<#X&E1Q(IAg<21@KVntcLE(xiF1+ z(kY8#eL^Mz{=;ZvI&D*rQ^jX{2%I^iUv}J;{B(hKHDXG!mG-rsSvx4yyvuG}Rw~L8 z41aB@hMrB%+aZS#9#v7Zf34HITco!zV?_pIdKnSYY?FmT5q-L_)ne@YesB>;0co(k z41Oy`2575TykUH%3tp`A#LZ(X^diuD7i>e@dvS+|Ug-p&aAQ zZfb+L#_AuvI6b$vwsU5+mDIHHktAB;flD=8(H6pGoYI9@aKHAbQ299jCK{DAc=yc3bdfWzr;FLEM-9y@EbFoCFesmAg?;3lRls3@H>9(6XM#9;e-DS}Y^*ZBfcYg1v#eKg8WYXT_@XR1nkr%OC9tZ6MVr3;KU0kP5*R>6 z;G)6g5Md0i_hjWQRvk|Bkpo4MgrX>~Tv7+_76{%rdWIPnj4TAT5Ga9@OF&@s(4k({ za07mF{71f58-x)Mn39(y#bL7j!2*0&+VOPGDL!ONv2oAd1|Jp1Yp+b-p&ma+$VEaX#=-@*~zk)w)(54S3*V!b%Vg{}X$K++9FFzMc*ok0R1SyI!nFXoI%zAb>r=DX{n(>gJ#5`kM;5x4^ac3aXIE zfOsS#i4hxXLSh(je(Co0Q7z()Ze}AZ0^%2`BDtXNZY3)7IE5lf_TbnvnYO9rUF;3> z&!|N+zO7~{?@6(fAt(d{(_x!Mv6LjKnhmEqhHjKK1{A~eO9xZBtiN12FvH_H!*0d?4N{wL;R$$qfC1BKggI2I?&zM?*U<4Fv+-fTXQZuyxuF6nlDXe;@6PD^j9h5Z=HNWF|sLd)AtP`Ma@kq1F-V zE$ydhIC~2yODr;o?cp$(5#z&bGm&~L-*!Rm@d%-D8C8t~G%lbcei-CPXNUs1357do zu-_k(`$8`_lj`H(f94BrR`*bDBVVtrrEB;)sWqdvJOSba4wMtPNvpvy>_HJCe@n2A z5oK_JIw+Y*bY08{LU|0&NTVqyV{JCm7Uv-;Wu(?<$d?1pG42xjvWdv$teOdv$z?(n zZaZ)rIh@cHTiiFsC~Ko^8DQP2#K_jU}=FG2y;u(!~aKi90}yk*tEFsum-;nS~@pm!c2V z;IK0q6#Q&gLe**Fw=49R#@nl2dv+3ZMsWb?ohNrJYihVha{DjK)gihZCY72%>nCRB zjbDLkb5wfnU_QhIa&Wroe`cWl&E*jq2zm&VrlB3ogfAH?C|p|Od8g$JvLu?7pyyaA z$d0J-7Lm4Fs0|dpWAN&X#|ao`Ngg})Ia3LfbK8;lgPQJ|SqFuQcum6*3#8e13?6i! zoV_FW5^OGHsDgsf@>{oaTQ#&04iOG^I<2%PN&cu?xojJcywtwie`}rVyxIgXHQRoW zEZ)|7KZCkQvW7<$Pz81Y>g&jyl_YG2AVWw{@imJKm`(s5-IY&VyG#a}>i@J4=)Y() zTJEQ}58LcLM>s`jk-DqSvo0cT=aU2lb)b}`1Oy-fP``at;gX5!Xj~}Xeo(pxDk27o z-6vQ#v}coBUX5<$f9_ZO3{Sy2tYR#-V@k)rvTV8I#JFO*7AKd-*_z9T;?RbNvLM=g zuOoXd{N05%LXVne^doqq_o&lnbeqH5ODE2mP!u~!$6QMu8cn1Oyz)6q$7ZD;e$I-q zqQotoNsiXa+4p6*&Tx|#7%~ zx_BnFxU6CXfBL&C*jt34oUne-ppYTp{DMGs8kb!4^q?5uRt?1UcjdC8QROsC4sx~c zt@+1J1|_MQ_KJyWHkqoE4;C1aD6)2t9@0Hg!@Jmq?5CyU&fuZq#k9ht!*G_$?-B{m z@nxU~RqZ6BPy%io5aRrFCf!>u-^a3WP-rlNVaolae+~?do}=rE`qM0-zrs$wm+Sy8 z4G@ppFl6isp$6evu>)+`X1be>b2TLFtpHdu`=EX~@ zt&Q&1j0go3df5WtVL5WM0`cytjpQTR{QyGkiWMRB(%wRGRnvCw8-=p~HN$58&QJm^ z&=C1%e_=&ehHB-~vOR-4OnvD%jonqro{KfuD%Z$w@c$5uwEwW+W;0RC=>Ap-TowuC z#!J;Zi0pR(FC`is1r)19jH*IBi{aPNqE#=VOV;6e^j0FQCU<#SJSR#*a8E%R3;N`S zLRn;k;%Rzi_yUIZY8W>Q+N3Ah4(eKs;vhh;f57A(nAU>(*z9Byk^QGCyM0IZO;2ptlPHF=yj6br>ym}08Vql017Uk3)a48j~?F*CtP ze+g5jYCWKk{w2>qC5vL9@?xC2VSexSAl??wIW&{ zsL-(1fE8b6gPaoBT~F7KGGX6t?eS@LQEps5IYkTG!(Q>+Byn3X1#dV_^CW(=M`$5% zJ=LP;v)(v8pb$VNt!mwBF=j6GM4odJx4yFgfFJS$x-Hi*(vND1KfuE*9ZMHse?@kg zMsPqkSW9Z(fiuz*wc!jzO`O{$Hj|; ziMp}7D}09Z)PcSku41a87ZEf6c{KnH7EZfav?8k_i?wn_%N+>aJ(3vvYc1Yc2KI;Ql=T45o#!e|lFej|J&`VfWD@qgk=-D`d^swHJ=_E$s^&U0*r&2WTpDZp`CNv(b^&8te~EOK7QOgI zg<>&$WAEnYdEaXiYi=%_vE$uAJ?s+q`XURG{7{w1z<}I%k^x<}W(35&)E)Fl_v5{> zgL2}=NHN9HT#~R5{Ej)#f98;vMZkC1gLGy=?+2O^T39U)ND8GEw1z)cCy@a}F>^2G z2Z0LRNzu10vp^7pFtI3vS1vz6h#-^wad7~RbS_tF$1+u0hj@e;#U;eR4C?l{;6zm; zE}3=;*rj=dp~_f$X(rXIrj2X!8M~QSN{nRHFAi8hWeF<0K%p|xe^YV`EL+JG8F7rO zNO!?8L~AZ~wL}|2Bq0L}5i6%d#Y&e+zW`!dx;(CCZrih#Hn;3i9Ycg1J?@*cIJ(gc zPaXGiBVBJIlu%;`$}tb_F>nuovnU<%jb9O)x6wY?DU`G!CCHiaI91mw)yPjz^X_d@UsO^S z7J*iRJPq=)%zD6^kHte{@46XDTO{7&`a@-E50x zCDw)IYFeOYR?ncjGVyD?8hBZ84v3P~N8};QxIf*?e8|@{K@-LOq7Pmcnl9j8Xj5Av z{8dZd-AWLMk)};+P5Xzs9en9iJO@F@A~UCMNz?);QqdX=q>$LdAB0o`wU?GylLrCW zH1lW<54w{he-~i^q;S)r4O^L9xpuiZYsrsJPPW1eKpx{(T1mjjm={({m=C*|F*krn zp=ub?)-k~*#D?$r9Ah;5sSg8gfh%g1|b(fqj#9dRse|X@EQ450@w}WD;Sg9RS-=a3P zy$G|t?9*ono!yYVApsX!JTKe9$54>NU*Lj=$U#%R~f4imQ)&b1g74hQRYrt%UI!yy4;B6P-z!zy9yyN-C+>Z#QnUb*~{ zRdqvWe?r1DtEQ~4GQm2d<0XZK3;e`5zXQ|^x8rn}Gfo;uXNE&a7lImiHEeJ=?i2`w zb}j8DjSrmr&=VhN+D^~ZM|%7`n^MX79H=r?;?=Der@J3sTU&uYySv-$aWrAw1!eC=J75Vle=pgJ)7h$ zku1(@?k!Cgakgh7UztAou^qCzS@&Ww7^sPF)YM`rYE4Jo1a=uY!S$gVoJJLAc7<6T zgR(cw4lF)lI>-n-r7y8SOdkyHi8SbR5IV4gCslU9wKv(s@RjK7un~@Hsr>}boPnQ4 ze?LACt<80UC7dM0kwLr$ELG5WYkmb^D&$*iUFth_pHFJ1=_#wR4XT!(;;3ILz&JqB z^g9_b=}|JQ&S2P+>I4|1w=>1KPseC4qfJYIsgcaD3*@l2MsCLN7NfA=*d_I*`nYn| z>Pz$;Tr<_Ktis3BiKK!Wgqz1a7x}@MEP9mUOM1>R6hWMZs zv#*GAaV%o@DML4jqi#xI-GKR>f6uOPUY9L+WN{2ZWjIzC^BPm-nVnSu5PQKitMnac zGDL~2&5*A}^LZ7iQ}n;t`y)CYqeepg3og*t6sw%Ee!Rts4^mn9I(hzavlt1Be{?8I z?OV7GkT;ONJtNF3xb~BTWp_94g4}+|s)#fSf-!=sS!(Sx{BuA#)42n zLs4xt{V#oP5-vG)JY~#W-;i@vPl&yO0%7U5rAjGd@un4ERhDCif$~wj39Z;Mt`+D9 zzX4|CG0+3T{IoSRE0H;&oY1z!e+&L`adQ)i97}+@Wl88Z>eCA(8=@4nQe1HnC+_$T zCQlc4gB)bL`W)Km&sHkUs0oO+Rvn`ndy;oqw(9r5O`7hMMSlwRC}?}Oo;w<* z1gvoXRc+q)Lealnb>yzI-c!8+80E>~I#kwCY+zq8$Z9D2qy4nO-!>j^c4`jBA1$*_ z+NFMw?cC1E6~uf6_ZDA4>F9_0}#|>0#|b zmX4+u&#H~&*^*2IHvA?U;RO0c15Hk1C>+DcM7kk7)rbRFi@nppzBOf>w^P1uk<~mi zJ;cb`aU$9Uq;5ZtOEeq{hsk zdLhY`gqM+UV|d~F!VLsF{=^33hDgJ88t>{*ZiWY>AQ;) z2SWuRSJz?{f5eN7?LBEd=cbMdsXV{A&eEeb`5wM{1*I&jV|C z5$+LobhDS#rDfE}9CNDyT!^Nl$|a{b-v+TFt)#|@Yb~A4HAL4vB&uV=ayjFq7RcP< zyeW*7?8Mofr|Vq^)r?TM@Y$2w9fd}PT2Kw8;rS`GfBo~X($xrf2BWMhYZW*d6K&~c z5Be}D<^mXCTDcY9^mM=Z5r{PZI*Q1uaS2}F%J zv3iLJ;PQs(CEo~B%VloLm#Q>bg?JyqK*tcqJX>wR;VW!28ws8=~r>M#&)tXMKyu6-X??@*RBo=6*Kn|m0bz__yv;$Vj6ZD}dN>D}0qMS2OmKKK>WmP^K_-OtJ3TWHPG(K)QGU zYd)-4JcnF>F}wn%F?{i_?lOppgscYzf74cZ&>ChDl3RTz_yW@YVi>$X*w3;)IyF6)-&H&o zY)|i1kmnM5BV5w12;z&4uK}CQJX}zxM3A-%5i>6q{po;=RLxV661@CPLi-S;f6L1k zig6EcadE%tho{pr51WdvXB+5&7Ip)D=b#JtBlyn2Pp%rg9N8^oDoM6reup*a%j`7_ z53Mh%`bF4UR7j|Q!}sC|g6rP1Lgn1!%wEdCA$9j?1NnSBV?(QufJ zxl;2xQYUKa$s3n`25D|*hu2cLNzsqk_v@sY=UCe{Cdff3&g$PR9T-q&dJNO5EteraAAwFndhb<`f5%BZBi&W> zWd`>~-hT8Dt{czU5mt})Dv}58!a!uxy_D6X!MloFCTZ|pQSXa=A~pJFWF?WJjBWMd zXSfRox)}adwU$b|m@th-8M%Dv%FP?kCl_yA-@N(!$1bYh@S&IOf;SHxMe=OH(^IvW z;=&T|8YbYo&~(IXG1|P^e?)aKljM6U@X~4#AW*b+G$AABdTH+n40{6ly-VsIv`2fj zmV+Ff&RF)#!EFw7hJ!eF!BurU?W*53I))km@(3efkZDv~MrhVvbnX3F;}ttEK}~++ zUvyA%>`+q;3LLO`e>ougZbk9Z9+cC*Md3yj*D(N%Dp*5N5s)HDv9fm3P>lF)Hikx+ zl29WK_qy!UQ?*oAX@8($XxVPM!$sftoG^1XR2y&gbPMZfCI9o~ADmuw1WIlJK#58` z77?-z&I0rkQTJ%XBdAQhfr*X6&oo6W5xG1h+P>d`E7vZAf3bsk(35se-K@ZKfh(p_ zs~Um^wYefjMC0D1xSb8x#n%!~50Qpmw9DK1=w?9?T9Tt93MEn1?gp;WRmIWg5IU8| z&8)gl+`N2!^NON)(T*Fw!;Lrr)?@e_;jit+f@IsAQ3O@-s!*G3(OTSn8!6r`UyAY= zZB{>O(p_VXC@gD|qmwJSFhFzXuvPRagcGAh?sSHYBZ zz${BPS-pDYqMFXjOG|=)YU(Mjnb}=*^TL~Dv2#lue>doD#a~s9X+M)6n+bMkFerxq zc@w8XrD-q$Xw=&6RrP;A-x1AW@L;31;If%mI9FPzn%=k5K@aP?aP5-Vw2iHJ728Nc zY&{@2fMuTSjEe)%Rb|6FrnS!WszbmGkb7IKfptENeitGoEX6l+z1+|G{d&tehBO}8 z0l06&f8l`Z-NF)6SMZ7rHeKC`2w~vk)xzgENG+DW1>d*w?QLYzRe`=(pByn^zAh*N z53Sj%fdCc=0O5Tj@}o_rm|ETLty;bd=^)}Y{OuL+FAOmKrLSo63P04HH1A`%YDN&s z36qs+7hmQzy3DIzLweDtLWfk`U6hH`%4|Y~fAJ4mp_oB06R*V=?cHLlmhM2(^x!u9 z*-6WN{F`N2&EU1eO>h|#8eF`M4eyFuUKgLBt>A-42x4KIuOvnA20kNrpr5ZL; z6+?YONQ>GYH(-yd+M}-QQ4jaV)SCT0`1f{>CjtHi`x36MkB#b=@GnSJ@$YTL5yFoG ze>@UO%r>}#q#Uam;u{dC;NQ^z{(!d${>7re@QyG_YU6>fYdqj`70*C_#&;BX!Jqr| zZ!x0D*&lO~Vmjs&JUeBd2f5@tx*p*4bxq|I-%M#Gm3Od{lPse@{UMDLW`IA_E*5ns zr+=|O2Puu$0e1O-hxUNR|6rU03J_Ixf0$vHKcm{S?bGpbwg*T!<7czJVp4?Z#W_P>?aV_e>IxI zJrW~4ZzS~>U#yET;%;JxcbCDjgF@wo^Pzh&O41ESzS4lt662fM2W$2 z2zvmYPh7mK33B$9j_xeJf1?X%fc@vxp!TXPAAZxwEW^;$Yl7tPY%g=O+@{#>OJseq z+Q1a~W244d7cFp6;xM~6@z$HcGo8h6Glnom>7B*Z4C3Qd(W`mQT-~bIv`gL)gCM~y z$hXwkleHG@$r`jE!*gifZ1@Ab6i%+}f?Y%EaPD}Ah>#=TvLH>}#-)38l;rDOLZ;lZq+`szjE<-PN@-mGo6pyUUzAOG2psBrazN`@a;EWUY#eo%q< z>FfN)6m=~hLPN0>DuVKJX3WXiFps+aP4=O0D)EEYzD())#{gSEq`%v*&<~YMfBHJV z`NEqz&FA%-zvDN*_-lUi>gUW4Q#kyl@^#g^?`J8&Ir{S${eSr&{dt`Je2D&hnEpIL ze?CHg&aUxaF6Znys$^2AQCY9u|K%SazwzT5*LgFa^t1KadoRE8;7@+6(%t{%uWK!o z%&gZQy#0muzV$|}1r{&qWW9E%{#zLgR(ic!YXbS65g(3!@ehLmR(PP8BRs;^&mJ8$ zZv9`=Yzz?WR(}wf0ES~RK1{5w$N^`(gT?7<*;@^ zcxmcGLMF|3`AZ|AW^#(9BhlDX3CkQ;PeYc|$xZMI19zI9RYzoHnF1QNhVn-BitOMgk@zwG~iuMYPP{@))%1ltGy z{grp$dQ<)V)%V{0$=~34cY0O*dy4H58mDwm!K8tk(K5sy1;;?;-u=zD9{lB7$G`c) z@#}wg{N^_w{PZ80Hi8Nh2zc$?w|;*AH$Q#w=HEVe^9?6OHc0b6C3yFr|NQt1-+%Dh zD-XW$<$s5N^?yJ7`ad4O`L*}{>re0h@}G`h``Phdzsy;tQCPN{I5BwOwk2J z@uZuMd(qPF|K|0FU;okZtFIq__2&=2`#C*ipMRdF{hNi#asSufRjDY`{kLCz`0clk zzxEZKN~>d{B_Dt7PapnDkJTW(OB~XAA}5@7W~27twU>|I_^acuzIFeX-=|`dduvB( zMg2r|=d(`47-REcX7}|HCPHPMPn1<@3ki{)fskVd`G~mFaGJcTRC?N{-+7;r)01 z6pITBP)Er80)F<@NC8WXWqpKds?*Et@^>!zV0*3oMDkgqSyBsdf4T!EJgelFa?bqS z=@&bz0|ffg8mG1*fQkSti9@@2FW+S{`+o<2K!4R4E`GA}%(=)bR0QG8eIxpV0 z|9bhq){a`J@xNIVR|}bKX!5BcKmPJ};Xpdm7_##VEyI-|V9w@)>7aS0X4k7Nl79}? ziZZ|WDzB_B{k>ZJSoi?6&C|h(Ta8zEpL%$$7-x}QQvV*PrTWHSQ7`}J%aDs3sy!ZK zjnbPL2ojykwKJxN*oOCB|HZ>^|5TMWES^U^+cGxJul?k~EB~x^2vx6Am+DmS?pMsp z*Is-058qQq5H*twTQ2nbS0>pYR)0E8#e-KAGxLgW&e2h`rPqu4!Kcp=+*?jHv{_BF zt%|9uGIk0Gg;K7=IQkksy6&ACXS<54zNYvV5SgE9)Z1xK&CLqQ>R0IV$^gF8H4#_| znaf@)*Q7M;6dSoaNilv?9j$v~wZI2?7d?f>4Oe>F4Kz|#8(X#lz6Rv0hJUK`jT+{B zDeu*`>sr2#Eiyby!}vtOR$}96b#p04>9F3C-_ZO@edz(|B!HbR45YZVPSOI{r+}G*?`0DUkAtz(Xj&jKWP=HpRwDPAc8i9kv=r(fBb4C6h=!nw=1?p4S3Cw~KOfzS+zedNZ_ z5tHt<)D{3-b$Tnk+mJhhtliWWd+x^O&AQwfPy}4+VPoQD-ua3wu=>Z(vCa)BvvH1Q zt_^`NbkuBv!oCp>K`?+gQ#5gP8Cxa_E_8(V{F4x2eKAu+7giUM#8T0gynnb-f^Twv z1u;U(N!~39YGY-jE`J|tW-gH(#*k9p_bgEHn$Ln2zcq>SmlQtc0 z_+WfD2txp>y{hR47^69qfYrp>D+w1_P3$G3N8YYAanZZvhSrp=gceo}>=>GC`&mC< zZ-R*JOj0|~g>3+m0sl7Y5kk}eqI3Gh<`(8MwUgVE>4Kvr-e+mX)7ou1+(isD_7vEj!U?e%u7nZyK~mNp+LkJ zV)0bizX|77qq<)*9XZ?rx!Fr-p;?>7(N#s#b$h`MlVA6c^`%)%ZF8&&4LW<a@zjOcXm(~4P zodY0r`+xagKm5TjbuHk*YxP930brZ|e6~Bz%6<1kIY`HoD_A3cSY3Vat#{P5{K2c= zd-wIP82#d5Kf8dg?N<@=OO~O!JrP?_vuAR&5kdwS!8)`A4z&-ht&Q&fn^G8R-xkj% z5Sjll^u>x1=<>vFPI&aiE~b3R(n0}1<;nCOt$(_#;hr1_xy8I9q+mhs`WifwZX4D~w?e{jz{7&^!R9aQ3%4Ea+U8n>+8d&ZtBetGmGI5s9%!fjC`mmBrBeB8<02={Oyf&3mCC=shjlT2ClZdy*;QDL7?hn54vj?yK^!Tk`Jb!rW>tu|`MtrY-(NwgP?d3zLX`une)GtAe?ii~Lv~U?J zZKMQ5J$U*=jlnE0RW%8}UOqv)s5rNEW+eaOXUE_B8ye55k;L_Kq7Fcg%J##@lQbU- zt7tu~ga7`Ghi|-d{N*n_c=dbh&f552FMm#UkVL??E_r%++a-2%fq%HoZaHuq#G7)X zM)<0=W&}~4;NLDWxoFgM0oId+7&a13xmU2tmYPjk(MsOnkJduSJg;?T{Ly;t!B<{+ z@Bf)IxJeL*dHQ z1-(QC8B>K*jmk<`gnzq8-|&z$pQAEmxHTE!rs4@2?gWQ69kx567}Yt`sF~=9WtJ>r zK)VO$x;%m{ALsM_AqUTQ+Di7_-Uw=RBdBQ(rs+U?I-+;thhxK(G-AD5mc5hco*2kh z#tJz8!jInj{EzOx{m#Q5zw_Xm|MV}v`pSE+y$mt~Bt7sF34hFcum7W{(mjF1h@xkO zJXySN7G^y>JN#niB#HQCOYc}G1YESe%QM=$ym)(;=eKwHB<&4V5pqSiG)=Avy$t5A zjSagYVtYzvb9adY04$CR4gF_{v1RKu!Db-es$^k14GF4yr8z8CaE*v^bmqEZlYu|d zN4YeLz*v2ok$-)i(+}OX11s05qLwFWDJ|bL_ zf3ZCoV|4P|kn<&c8|DxC8;nqt*q(sRK2dugxuY>|`Vk6v6#3y6Ae72Id zN{c`1&7+na8=-M9`K{w^!(wuW$%1O?PFBfjLO&%-nMu)6P@-+CEUyk0DtgFOVHtk3 zWXWZPqJQJ-+@*2g@F%)_=`~c9@lo>Nik(s0qZ%Tj*l?2Wlq~R+qDI5&C%y!-6iRA% zjG0K|`$v>x(y?_j-3e`+sa(BayaJof30bFNggDcbYmZ1T(fciuF8A}h(;X>xp9PvlFWO zeQ`Sn+dLhbaA;2$n7?+u!lipd$U&_XsZfBBo3pykEuu-cg zXMZANa3-l+gC1R2C5bc%C`N}mo%u&yv|BaV=C|#A9|`LeA!gqn${H){_oVgrr1f|0 z^8tY|D~<5!<05_?`7obcf>4DMXpXr6kbp5`RdaAh&PpD)FAd5@upx$c*`ItSA{$G7uz@ z)dwK1=!dorG~hJ!DF~tNSz`<+90**#Qs<_0M7?j}5Qm1mGGEXzjDCyBJ_QZ`lnz6W zCPixHPx}zBZUP~cIiOP3tHwd~Zh@O9vk$I->d?XurSN_g5`Ha0_iepqT6_8SUVjh1 z^Zj?<`W`K-)#F#casSt^inKE=y|mbx8`%;uwHCE=`YkM-s%@PdyRH-1JI%0oqJti` z_Dj^;S!PTqjLXEQFhV55D@={kLCLFXgUZj*&x*F`RbNubUIez``-uwKI-uvc{jK@xt*4l`mdUM5UdVe<9 zd*AxrDz$0O23zwtm>B5)pKLPQ1wkFU!B-hNd~JKD&SD6Snbhm9M`PU!7NFH7sfa@qyv&Npy%CPKHLPGY(BLt9NP zbu$dh@t6Pl_=kUT{FT3utcrH=^9CX^3{@Si>Sm;q^Sc1UH9(P)&b@p03^pXyY6a3 zc>mxV-#UK#%kp)pUT@tqUmyJGmoW^0csy$H=i^u2@>1A0Cegb;{eK@=1E=6eTgD&% zSmm$<(BsjzZzk<`sGLlp=Rt?mB7gYx?*tv1Tb{H~4GO*g_MfY1xc|;O$A9~GRbzGk zSD#a99{%+8hhO{RyDxvi^vHj2dQL}An8ANbR9Fl=Ul;6>G5W)Q2gNN6?J2xO`~kdc{mK&vdy z;o~v>!!7tFK+?@Y+o+buBi16{Tl7cbsdPQH6Z)K;pp^n}^6fVs{I}PS-}>Ui?|#le z6yAUP<#)gI54B2PwBL=B_WKDuM8cgJ(n@QprnbZ;F(TKCNxpj+w}?2^9^zNQ8}b~$ z)#1-yz5nai9)EoKYsY{5ow}K-dp?85{7&6xUCj~SFS@q@7<%l`(6YiZ(8xC-n+8g% zmTjs;7rGoAGy-gNYC3e2*r#?$A)rfW&`{Rqfg7pDvU{M-E1d-AaoOa0hJ8jhn+pUU z8%mVdu?nA@Y9>2mHoX7={yOlSqePc{(w(@27f{(Fe}BRSS4SBiVba}+sGN3xRwEPd zCUARVCw`G>ck;eZ6HjISdzpHFYW=DAm&UBACq>UAOg&|sJN1<8M0;LlnYrsLmrqp* zi!2`}?|+=-<8&)RJAOyY>vV7h9%l#XxR>mW(_Y42ViOFb);+_E}Eh(f`EJ!J?LP z$zH$MQOh5%lzZm$(kTi5Zi0N5*+kvhK=A_HiqO2k)vh{+w(NyWWZDZYylL)!km|W{ zv45xfUOt_UFDVLl*f_Vg2B{vw4vUO;$X05jHYtk!Bp=}>;@`Bmf|R3TRNMi0E0vOe zH%!>><8S}-!&koa;5*-c_}ZTwzwtx$NJZp>J-qnl*}+Oap!=v9n2)QsvXEVMXzeFy zKO0XTeD!M&-+1T2>tB5LOFudO;~yP=;eYSn`{tWVEQ-?93RB9(jxXFBFGpa?CO7jz zR!k=me1UlduB!`hgMRWE+5{^kcm^_9l-9_z1=!zf#vSmtsMM*iy1K`8b-b><^-vS* zVJB0BNNsnJd)GpHyMz zyq2W5)8zSLM-`A<>t0bMD0=qUShr`QMAPwQPPN#Ju@JNDs&fs5*uBZ zt_DdM==*t*<=tb8-ba*eS%0?WWo*mig_OKJh$5+$jFGuNbAWbXk3p)(n!KI90c2BgNwFVs%USEvar-rx{%5a-cHp!S?#n% ze;4>~+xNp1YJzn9v!MQ9DvD)k3;tc8f7||t{BT4vKh{COf&gv5>3@&Mok27bKdY&^ zaC=PXhNv3A1vbLtdND_?bDWbcJIX_-4mx3%YjJP6!RhJ7q|b%2fc`o4f!m4)sZw6& z(Kg*&Y5NzG<@4$2xO|{HCSGPT((lt}3K`t*eh3{aRdsUEvnqldb~X6X{^pNEpMzZL zVRSo_t*qn~1W?J*_J5^zReHEpnLK8Cpl3`Y7?aLA+UA=$Z6A+0en?Tea6zN*NOd`)1s(%~9`L@*~ z@F2La!n7OWi-kY~g?Sn^q=>t#pXDEN`a$o}8(} zYOam*XL?$`o$6vmA#6BPHJboXO0pyApL^yBsakUvNm#~XF2hXd?E}E!6hA~LRDRl~ z4@sEoO?KRocXrMGy^sQ7qP(3(Nk;}E0cpldgMa*DI_j>Wp|Tspioz1UX{m4toEEP? zGcx_d{ERE*S7-Fa+WEc&2e6hswF}oxoHbC{l$#J?&#d;X+vtoeW(e*JFH=_mDXOxg zp1CHf5jSb8r{E^jf^y>Z7v`%lMy5lW>%!UUi42axC!q31u;AXsA63sr3tz&ojSsy6 z?tgIF_Jf_Bf!s{SpW#47TK4l{7o;i7?(|19F6vWk<4C($vzYJzwK+SF2Twx)^_+|9 zdXw_Owt26!1sDsC1)=M(J4U?K#StP-rc!475BpAUkV~~EH;P%7bTi2NxOTf9#Ru=L zDlX$x#$w|x^&Ff@X6U9AhZDvMNZ!e;DSwu2f=KXqf-*=WnAwPjIY3yjF(t< zqK*LYmv>%(Fd|LDQgmQXE;RraO`Fm|zfiYk!Sr0ijE{V$CId-*#ZAGHDtC4!kAJI3 zDLAq;b@}22>}3NGs9|vy2to_zXf!uHJ>`BVh^jj~lfMVN0qt$&Sz%G}@k83;?4dUN z%W1QYh3$jv#T)}@)>o*OqT@dIccz0C0QQNY22N^wQkR|`uWWMdGr*zE?% z?R&GwFz$g!49;rY6A!}qwT(W}=zq~R=$%@pLpOXSjeeVyud}P^N(Un=Jai;{X0HFS zrylFC9slR!j~+jDT>bCq+1c5x#~*z3_(}Ttgi3w%IQ>5L=rhNUKOFes8Zn_ZikBbu z!+x>?@Z82F>oDfW%X!uZh6Ut>vzGd*Bv3B($y0P%a;d~;sG0fkZaYVDWq)l~H9ZtG zv30`ZL4+nYeP|4$U`~OR3@^;1s`F}VD+HO0mpGn6@hO+)GFq|Wqz6nZ9S|ib!iPny z0{`LUh3aHJ_eRCV$j9OZeiS)w+U1ligtbFRBovnt4q|REd_N+4FUDFu#IRgOk31KG&eTO6MspX*0OU}Q?#fi z6zOT$jt__NR)cj>up6#tpM-xigmU-?Hb$dl#Pd!vR943rbf~dymAy^VB`9zKG<0ULaH0s#7k){ zy!m2dZ#6ea8U_8K3V(cKKRpeLd2Sq3<^{5Zjtn>nw?P$h1A`r|j%xeY0EDLZS#|gj zoIOA=1qM~kpgZYGWAFP1+R4b9!MFRLXc^chGAZoHv}KcunT9$8Q9Em73JVpxf-1P6 zONt5Q$cNf@+pf_uP1;W! z4aO9j#IlLnn#H(k3NI*_PxsLd+MeYR*<+mjF` zPGa#dYag%N#H++WI2j;67DcTqp(x&i&J1dvg_tVp>3@{VjCJY9#GGi4n3iBmX2>Kk zMQIi|<$N8*!qNi+yM%d&%yePY@a^Hpn1s9Si6fBnR$-UpjS)@7^;1ZcSNB@!SlRBU z_InR_%DU{y9XU+;2f8Dz?9Z+4CFMNTdLgH8!0_>IqBq|<(we6fRFiv$=H?%2&d)dJ z4pEv4yno|$(>UwKl#;B+X`d7RVHJO%y`4UxF}}(cuQJa%sP);3{|qF7q}-!-{Du^7 z1C9Lrd4IuLAK$;VJ`UP(gP*=uwA$I>pZ}I@j57V}fNi0V)x=zm3R^@kOv06LHCzi* zG7_wUY`+$jOfzf8Ry(URGr=-2!ha-88piyxx_=bx?BEw_-~F)Ai|pTR%*O7@<&17h zyMjV?hJ_Wk>XKi9{S_EV;$$~VlGf_7GA{R!Jyf*2GCjQlTqjJ&9jgbCOLMZPjD$%k3~$audtQGUW$hLLAUT}VQQ`o)yJ^>dkMO!PEP~(jLdJ$Ff|YIupXrv z41Z%D*J@m4R+Z3X$BzPrD%EbA=D~e6%`>>vGNnVq^tbg%`WM=Ps!hAA2|Yb~$!a)U z)=e)j#O=5#8S#p3As@=7MH|}k^z<_08*DE}%ltmQ-|_=(QtQHs=|z&Q(>vDfbYZ2$ zQM|ak*j-v0OW%n$Fv(22-LR)tA+A6^uzxhHCDwJ;RW|?vG*+VRUbf!eUd}GHyJHjv zLE40k5HL`HG9|8{7|~1kivp}Ku+ec$RqT}hVdWqR6h6{loxajiw}Ve!aHc;Hhh17v z&}Sw2tSAYMbjI|c-5APi51ZJEbrkC>(b^+6?1kIt&$H5k?zW(}EPtYw6Y#@;Dt~8C z15nCfK0!WxZK0S;KA?gj9p)gKjVkIgpCq5Ui(Q$IK0!Y896tl{LphuN!nu$rm6`AZ z=c#T`f06b!m#bUbT&A<*YE=BnSID7!Y1Xe!Pp_I)x?)L1s!X&h>mYo+2?5X0P73ZTN5V1Hp*$?r0eir?EMq}{fFT|2*ZcVb-q=ri7MGlVv` zDl{Gg1>2GqZ*24dUlh9Sm18YxK6}x&+S6KyF1F1xzNecGyFu8PGIZ!Mjp-Mx{wXJc zd$F?vm33t_kSRF1qD2rAoEqKXg97D5;c@}8wH07#t5I#H&g!uh+E06WPJbygGYe+^ zOu6Xd$`VWsJjQTCofTk`ZtpfWbM#5*K<{jtbk&egPnX8LtA@I3jqrjQ;NBhwxaSTq zr*W$^%*HCu71O(u9P4#@By3tA7kf(*MhjgwHpqk;FZY3khf{L_+fhLr zTDEk(dMj9f;Z)c~Dr4JM9%i*APzlpA-H0TA5SGxw^JZ7^101PJR)1g^fiW z!>w!9x_d=oDGNWTQy>BefW@WmmW0+VX`tA&`&AeN5ms?)B(JRVxu9JtU7BC>Y+J0I z;i!TuG*Frbe9Q`82!GFq{ct@Tgju*@O^m6AxYX*g>F(^PMT3&y+%fpsJytoqK>!sL zMjnLEFvWe}lAB(Ls#F9kW%*>GYVNfwGKS})ZOtGw^Q@36(&_0`PgdLzkIm6$lfj(b zh~_)pV_7GgnF%*wlJ*Nd*^m(>xtOJ+^+KjhX52u1AC$k-bbl+O278F!Kh7`qm!d&g zzF420UN=I~`Neg}6?DvQlftOl>~Ymv$#M7svJLW|Q4>THDqKZv5(TmWniSRnYf+iG2tI~QVt>M7aXM};qtaoj?wg)ys}aRAB~#{jHLA-$t{yT5GHC)@hRz7c(YE>tcs;t0%Ce>R7J+(j!diNe6+IQ`|X2A)qfV}(e8!%P36MYSPNzj`p5Lo z)nLXyI;-*?^CxpYT&|@IFHBFrpk@2U3sD+`ec+1gQCD{F^<(``AJ+2unWz@4E^w~J z7nWSyC^21fFzgV!K}_zmm2wk>`jz+M`QUzb(lY&$N|B_I5Ibiis`3P4!8u;~6ecC6 zcXSTxw0{H}I|qo_Ab2%ac6Q1IVIRYDjnQc<`C4%fTPsp2KCgh}ED}Je=a#-qar!ul zwR`;R*?eYpHN-=B7)S7DCZ2(RLnQ=uCkcUS(sPh%EZHp|*wCjIsy^1754L+z!Ys6O z>!%0O7vw=nb|#t+E2S*db0Im5nkOo|>n!upnt!;c*3<@-%AsgmBH+PU7qvume}&xJ z2(r{e^joWersi#RkN>}Z^CuNS(zmrcFei=3!#{{4`2*k5$w;=%Wsnwp#B*g((LvfK zLsp{3*z?;qd!BjERMak8?K3^5wd1ADS)n0|OGad(sff_N2kAI5a> z9IFO}3N#vDikGg<9IDVhHg-PnrdEtmd$=&dZ}fpZ8n#6@Tvl^%)2V7Yo}?g=vrb@X=it>bm$!NCzesR*+q9&BBVx1c-?jdB|1 z+wqD%>Vq_f?>+MQu9qxtu3`e)mH39P6x$~^b}z<5z!rU32{VJ1LPNSHXks45w14Fj zLH7Yk;UD!Ge~-DpC)Segc^vjwYRTwbR9a8!fz*p}?!|o-Ri+DnpkXL$y)l~6Lo7-F zpmK}eoVSD_J>@$iL1Zw6xR*>?oo=Idyod4hrGMTiUPWBdaPwdbawum5+=4vcWW#8p z)-P4f+b>$$z~H?aojmZVzq00u|duW}3nrr=YUawrt$nDzE(} zu)3kGOCxEX9mX(n$T~KWlW_fV?JvXoZX3z4zvaOO*@HQyu4U8MQF&D$_wa7OutljB z;`H%RRavB3Z}Gc2D(p{3BXS(Q^`W|r4RqJRxn~xkx4h-WJ$#M>CRi7(T7P|YIS(;J z+#R&3Mk3(>MRL!2DF`S<<%xyx`miuoAJ3@j0VUKV#TiX zB*fOARslCv!%PpL&N5I7#D7u*^CXeT175Z{+SnYa!fH;H0(RPCrZ2v$DcrE=H1w3x z5Lq5ZzV8^6PQez6H)A=6iqhmE6Z2TUTW5@kWav3TOtmzaw90TY*!83swE!D{aRc5z zx|n(B#+$cw5zlLS$0-VsCj%UN&#USmr;ZGtcQQj8!$h%Jj~}n0jej%AM_zA}i1<88 z+oR-p4zL7UP7kUaWgE|^e2u`a(xb{yK7_V$2zXp%f&ku#vzLwz=4zZ(;o`X4OaL~i z$~ocm3xn;OJlK|+!6TaFdieG+MKPk7=O0ysrQ3%G)t7^_$6%Fk=6#yO<4HBFK~M$z zH)ZeugVon`N1`lSjen5S^0S#;ggG8PHO^C0=4S08aR~xso0_zsiF>S)C(wt23oncWgLa8S&Y5d2;$YSR!-qFa|>ny7WL{D zp}mvrfr>W;{4AwX3suEdRW z^zKck+G00N-DV*80)~hm$b9Hy$4o87jLb~2an>-NL%Q+Eo@pjuP#(>FRrw;D<|@BE z;Cmfxil7OD&5<;X$kNT$*I{~w+850;<~=MOF$r8!|JDcnT#Gc1Nn?z#7lae zy&XQ48)famRsRe5nH-!!1 z)uK_?`^vbIXy(IV#8)z<(R&o;irvltuYP0bOZ?Wb*F<1WYR}Mqti$_z=(Mdu)P^Yc zdUWraUbSKw9y$yE;cOfw{Vl4dmtZ6{7ZtfZu7Aj36Kv6Q26_p(f?d+$OoFnm%rGf) z5rschRBNcTYwobBEqfDIxAV+cC^?3QL#>Mf(=mjZ(0O-fte}HxT~<9lS3mB^6repo z`5T4~1tfy=^Oyw5pFEy0lnn0ZTkmGLCquy?`Qp ztws<(RiI~*i^!>MZJXQF2$qFG^|B}`fPX!XOnHJOa@y@Oki~61aB^t_q~JW+>}5F~ zK2^%1=eK=a=iAifgT)UAJvwnG1KhxJ>N_2IC{QGfxH6d`4`iM6eCy$scS24($P9Yk z#Wgqq^@iET2JXi%{4-^`MCzq%INF0`L*dDq(k~EkD8UwSVkSS+W{Tfv^?VGDe1Cwx z%Q1GZ;uNgVe$umBRVh`?vLvk}Rozy{5#&hBq0Jaix-N$JdC!PJ>!^x$anp$tsiKf0 zdnia^s(>$c1U-!~Lf>$+EBbA{$oE?d-hQ3M=!BJMj%_;EshkN;q1!!tTh?JR;&E*( z4IQqXt&VyIeCJcCA8;mn0k0#0{yUGSn%lw9iv#|As_fBeWI4-1O4!IMfw>B zzaK9refmIZixa5$+T73&YJYJuYcu3Y20=&SGPaQ;E-opFK^=3k+UoCO`!SWJt04ct zF6g(}^VK9O>$$-u8xTIJ{g$c`J=91kgJYbJj;l9cBFUg_1dpe^L>Obj^)ken2 z$|#e;;>PCC$fkD3o;F{)S4nN+xpsp>;MKuey1LdUi@26XYqPL+Q-3XX?nGFq(M*iu z7c&7|ah`Hv2GR1J&FCV=VZn-sy59>~iZkJYV?;`mKFc@S zQkD%8FI!;~0v;1F5q}!WxuP@3)cH|>=$JSE5T~CQ4f~#z{;)LMA9;5AM!lS|$HW`8f~{S#1=9#h4ko_{C= zV!?kO!EpB>bQu1Fw8Ib6A!XlTNI(2Y2nfM{@C_OYrP3v}?v>tztZWz8(yrRdAJLjC zo)jwRxi#I$;lo$LbUNVOO;rQfpU8Si=%TDtUCnttO^rUrb}QM#8mP=6D*Ag|1Y}mP zTedRUFb|nam4C}q=ndmunkf@tPE3-P^m2A7$qh*-_hVN)x$&olEELK&Xr5ZbU7pMo z>UnZ%0mL^{Mbwd0m3R`y=Dx79$`=W#S#vc%v3Rk~eJ#!?O`w`p%`Kv_?_z|PoE|0b z^8$UXAQ)C_o*U%UD{+3uRB^x}|9w^`J^;$$#;NkF*NrN3KljWNDvxqZtImYqOs-RBo|=@= zYe0rTWq()xq;u3LB>7T54$?~$Q1_XCV2pR@hZr`s=#`DNgkyw zAMF~2Y6h9N4iYe#oxSb3G1@MMaTh-2=*33$nMZDSuMc=8{v6fRHAKJRd#H_jx15YF zCW%52H;Cn3mCv1S;eFPvdmdl9mzv-pm47Qjf^1L2hT1Hs*P`UT)VE50f5VAY z=A&d|Z*{J3;zKumk|?51Dc`;e$)$(z^WXQ76?_#XR^TSkAjBZwJ$ zGk-aO4-^$X6r2enZ?5#MP(nmAHx)QvLJBMqa9vebktj-@Rhj_!%)QjVx5uoP-)9VN zq7HHCp^Dhb5s+6yp1|%ARhfL%7utgPc7Wr@f!|af*W6+sEd>+GR$+%xTeeiHFkJMs z(FzcB4Jq<>$fiWMhh++|@or+5hstt;M}Lo{NoJUalCSh;Hr-ZHDjN2lV$!qk2+5`hP7h(H$ zsW+C9+jdbpMM@yrQAI)nJkc#N!JUPiv10TANJxvl-ttJAxtR9*-WqwZc_4rc*nd_F z71Al5ClFQpJQjQ2@@2)lFyh?Eeyy;iDb;Gnkj!4qH~@w+npoBWQ2I8>UA)Q!A6ibL z&yu9<`FOWshL55Y5?gCHXa8M0`iFRUmExAFzU)|M*`6h7(K8J$kwwD{9Qp^Du-s~# zg0hX;siN$y$Eq#cIZt`g5Sc3X41da`TzFX*sJ(q2IFsa$kU>vLuB$!#hyIDUQRyIIKGk-fLs{<&h zz*S5xr9e2i-SEbl&=yx0?#HO@?1!J=s%pxv?t$t zwW>+Op*-uABEgy{4mPWk1}d zUi%oX4A~RUoF8{&&{qG(&lY4A`tYRDGhRLO-ea0wQJ#Z_FaNst6v3dxq% zGId+5bh2jW4SNDFItbW)OO67`o(~do&~1_TwwgI`pqyJvK*|-gj;jgkWmns+{VZ8*CJ}FB6_oT4j|=o2NuU2G#?epF$dKj za9k7wvIaGZ5>*)$%Pqbz=Pp!FqYE+*FF2Y+t}HP30(i36l>#c|Nr0DOOR9L9oWX)Te zuxcpVPThS(U#IK!)LVEmEpm!#Mcy@ecZiBCT#a&l!qvj7Q;=O8HnORq(J$|>x&m^q z9Ni#}Ox^r)_y_bOZ9Tq=%j(V#+PHPgVAGJh&EIQ|HQQ78;nP_s+2iQ-IA z6uTc;mNaW0Wr0@zD2r?AdJD!((3y4-F?GI1QHHG6@zp68%QB*NzHoYPUDBwK3DrSH z8Kx-8ljqa>_St5xV#|0=mg5!7MCPc`NXq_XovO)6wb{1D-E-I3WVM~kY?SRf zUpD1pL-%8zAoYEt;9_9rgPqHX7_t0<4A|@g-V6C!3M^`KfLHL@R)N7gQC=9h&VK-nvK8fIso2TsRrh1vk3o zj(6qket8!&{J0ha7!S78ojH)tFjqBN>3_he?6+4^ z#eLtQXJ3~j*ch72wj~ef_fb9_7Oh|ZCmHS3nU}gFH~u9zEefYA=f1un4=qCS2T~5gL)0+zO&}Fihq2lV&%K-zx~=3DWzNnwl5V<^a+nB0 zQBH8y@<(52gR3j88JbdohV2|(-vd**WqLQ7mtw?-u`PCxa?15fQ@4`}(SNHB*kAPc zGC!=5eCQBlgy5)FJ{JE2-^0tvFJvj&QFLUl0&8>2iyCZ(3e0#V?|H}7rFbBsXVL~h z&>FGLJ=Jr}gOV1bl#aF#_uM$j@PMpV&Ek?RqG`RA^~J)l1~C_V`zTtejCL!w4zZJ} zZ&YDv-7RPY6ZC6NODA`=Hh=8BRrf|iX;W756(^fD4w&!>2TGO<<+kd0vGVC=!fqnD z?`<>LV<{`f0?O*4m-a5%2lS$!EegCkP3)b1Q6}2W3)cv|=EkA9AnAB%o7OnOCyCY^ zfR$?{j)#{{i-ahkRm|U7j(exbcVofxpNyaMy|y8og^r;|{r1IoJ%9Dk;(@6`tyRcY z*@)>f`W5)jDfe{NOE4%YNYEG~tI;JhxHs+P@k%^Q0|0_ReZMCT4r-cm9R9h`n?EGi z6Hc_xo?VI0!{QmOojvQ9_5iyemMU&&Pb8~xcS}&nCHc8Qda1cgfjO~eg-Gv`@*W}K z`xFOu_54|VTu@YnY{%gAHxYjo%rwK-0v&ulL2^yL*S4w4A6Vo6xS4ZoFc>P@Aosgf zR1L0jpR0DBvl=%ZI%kKotCluuyuZ|hWrd!=pprcpQ7a9xp5>7!?scvsyb>ww^9bv2 zSPfrtwi^JiDbYODT4+8jg=}m^AIfCV-8!A->vX=1%r!q*Rg-S!*yevXmH5~#>%H-)9GNJ(h$D$N<~)t*)o*L1_@W0uIK|-GE|Wv@M<%P zpcm6TQ8Dk_l2)uaF3>8@BO+_d!mJR^RtRk8C>1I)-F~x8bz9n&ws|3WACIK_T@smi|k}GBz8SUX1 z@H`^;yt?g^6p(nHhx2(uZ!3e#^34aNI7_skz&-oe-+WbH7oTa^Mj;D>&Y*C`@vOwq6)?S2}+|r~I}zbc2_8Y{|0J zW7;ZgyT_{hRzXJ*PqK!l6gJT^ZEC9V42ew#dTBQvC47=I_bp+}p>S0tD|q%( z(adyhJyLD0$HVhXT%{Nx6%-ZnK%~U8uX5j{zV9!^-J|($m{N0{xe^H{Hutmc|JU*{ zJE$CrY3X3I5Kw=vp8a+9*B~c%yRF9SE!jq^GT~xx!8O$l*Bm$5EDd zhPzm6MIgPRDsf-UHR)Y799qTE&sISKIC-g?sLO*{mrgW1{L_0pi8*iTfVqbsTQEnI&SiL2zzz&N%%@BbHc3xi53 zS}!RYC{%=-@@%ZSyy~jjT~&l|A=iX#&co~mQ@)>C)Hi4&@H2AoNF)lSP*FnFuEO4- zj{w9ZtN_M}45})vX_38w%N)#A>}(YmNc(`RLPOL3Y62(Kw5t&SBH&GMX%%m3sR7`I ztem;zL|K21x`7tl)8c|qac9zvRb{jpMlw^b;{JNRiW7jx8!ufQhebb!ww>%bG~%3y z@fmma;pJ>f{Ka=Hkc~mkC$ft=XTbW?>ZXGCH9Si5STjbdh6<`E9hyrLlvvkG;)scE zW_hbI_10C?fpsU^2r^amqz9Z8*WsMFZtaM*eN}(DJ{`!Iqnw1wKuJrNY>|q_Ia@X! zQ`yVflY+-+2mTx_1!Hl|;%>Z_D)VJg0(UdlSSWRIr{fszIZuFUJtIGO2XU<*RAJUR zwl()xX*-o~kNOx7H~^#9PoZqw-!B548#;m9k$K&*1hZd9Zx&I;=iyO-kIi>mwDHZ% z5u7P2GYiIvKC)R(Nk-LcSksC6$-6zswQC-?~$O&N{7cPM8`tKE_bev z-+HY3rMoCroGg(}QNOqzzd+U*x(?V<&r+aw%p~@pc3Ru+X^ssw=g*=@NC{(0q@)$a zt2Z*L9-g)hOEd2*R96WUI$M!kIk8GvjIV#tAFGfS>kf`E^vglypo0XDV0wmzUYoIPs4H4%uM!*e7CoZ=wyy z5=~P3Xld{0#He7;K03>VeX2|}izvIUCaCh5J$qo`>~`a9Zzec9o?Yz}$6k+J^&x-G z3@t;B++L8>!{Q!oYwj4O)`;vkQg2YvQq{dzX2y=((?Y-=~_=yc7?6<1S}pH>OBHYM=Q$|?h)RXV`5nH#w6NnpUL2Z_gsH`zq4Sx ze~$_Q9?ePas3m7Gryz|$$s_D!t(S{!K`LI3Fle!t-bwo=ly0H$v9^r^jglX-(p8td zM;x~^2@hAacI&BDb5N7*PctIg*ZA@gFT7Kah2Dj*hQk!}GS0qn>M_Zh_MRF#MmNdX zOYjw=<)ruMR#AIz-zd=8mbZU==kB874Azo2ZtN>?YF$$qW@X({P(0IGJEbzAQki^^qWL(@xK6 zo}P0WB*?nr;g+ruuO(gD=%-yc^=)|+PuDB5$K8|b9S*XAVmQ?uU`4*YOW1}Bd+%Tj zL}zUE+%DcC-Eb*_?s6>&xL<*auDk5(@SXe3b4xu^6eR;1O}Z+UuBbugM;46&wTL&W z(>?9RWzg3y-n)PAhj^>sB2RJVO}crj+$c%Q)$bdDkrg}?0gMV*!ETDTY%3o`sJdaR zFFlKiMMv7Xr~9_`7jEr4thgU8VkK&FUnmYM->y@WI`l47#OH9f$qJ&E=ecz$R$p)} zm|F@G{gmvL;+bE2&`_-vZag>|lBq&32zIjB%adSrk2odlx)aLG2bAmAI(r!!Z6v?I-U6U;A_%EVgnGrHxJ4 z7<%atS^>^(NlR-LG9a73q%ShY7Lpny? z?_44=p0t0Ca{f$`=$n%9M%q%hCE+-}K8qIh)oi#mtDlLOrMUgxi8E*R^Zlq%+_VDq zk@cO42U4W!9cinxA-%~=!X@ea$%XkJDT<}4iyRtQzmMwn5$($~X0sSOX^3}DbT3fP z?GVp#CsvwV_f)46ErK={&z_y~KXl;3(+3;D12cbNYqs4v8Xa5shqH@km;U|v?Va)e zvlI}?&z?On?^v#6N>5lB_R+AKQKNL;@akh+FSz;Jwhgx!*SC0%cAd9&iP#H!6nSyZ zir;2v;z77x=`fIr(OaH1MqaJ#Mc`gxv@HYGPN1$I(DDAocq?ZCi?4L38C_@BoNyJS z;6i_{@!fqGVY(2Bc7#N;Dcyd{M}^q4)r90-8zhX z`JyF9)GPE+znP^6BI_lHcge78J*CAFmD;u*1h;(UZqt@`)O@Qo>pmV=LKlPVC!ltp zNAJs(*g~Leyi`#Mi+2WXrWzjY_LkJ zNWA;}Cr;Rk*0>x1nl1)Kp}ZN{=r~|2Kloj01q~?a2dn(kg8jjy~OuEGmDO zhHJudyZq38@52d`QP;5Lj5fCVrC&;})NDGpW-Cx`HqC{^Y@LG2NhlSdIF zI^N4i_sLm1b=Od5%C^@i2N)R@-{F5I`3;}BCK0Xfb#Hw;zUqg7ob(sbPhMRQd@E9 zJYsEK?p7NVKPXe&iOUaV%UQNE7Kr_7Gb_<52G$OJXU>-Ue=4 zA>y>fezN_)=thlC^p&hc^l}Dl;5j`Q-tY74+2jhPtuOHQ~L_i-Ts_p1M~yg znsmudBFXF)9d!lo#h7rCUR8e#89TnL95_jE)#aKT;l8=t-?WSxh1w;TUmdr^pIBSD zO^nt4Eby9L8kKCjwpv+VeX}PK$vw7BdH0M!x#lt!99Vv@h!nH$ip#|MC!(`=Ozs5< zsa4*+q!p##Ha)|;aPiFw`)yBL)85#6h+^AgzHMV^Y;46Wf2D`s=3Cvl8kP zf#$2cBC+iWWR>K1Bep$(%(w0kZ)$eqA>nWTQh6leKMQ`(l-~Eo)F-u{ohUasULk+0 zb8vOSyB4XtXv&kosKct;y30bywo)abRSAz~VKDQ03EIAc#&6wHvGS!fx%-M=#W-R} zVD7<)dYqG;8{_4-{fvJ=fqIh4XLirH@2@x%8J6Flt{}3z8{6;2TW`S&?TK{y`p+%nxd);E1jxO?85vcUy>oXf~(XtLnxOVSsEDwc?HTP1-JeNHoxc0C>JtjCvj@U?%8S?yQI;stqa>$|fQ zh6!YVS%vNng{|H}B&DFz;~15Lyjt)i6|e&O?{`8^drxg7!`M5W4${z5Z-c4f$h{}y zCy4^ayIQ}wV%;EyT)J}mE*UlMcvhQNpyd>?Nw$9T_JTg^6fbG<;|tcpbgve3M!rj} zE>07Pd|P9vubzLjX+9{Ou~8awEO1NMrW;m?GP@#`wR=DMD?F$RV4KxgYyF3CIOk33 zdtwTcZsHd%;;$wny=q|H<5w|3IP0Xt{-e&7x(bbgO+%SBSnQ}eD9L_w42v(r>}T@O zTIiz!-M(B+180lLQrs`ip6dR{3bCGfz&qp8hTL6=2d;mEv<#hoZ`;1|qLwpVXBjlr zwHRIBIyuTw_$VnG`958`WBaBxo%zMQ(%T`W;I1kjPdBM*QC$zkPM~_sA<5K~UI?X| z_>`d#DZvm+H?5+~RI=B}Ox1om{Gfi$3D!%zrJVc`WyR^5^PzWW{>Z~eK63b>BM$?0 zPMrjrAc21$JapvHM?Qk@EYJ;qNY&g{v0z~j>K3SO2G{m%bAHFvx}&NR{#VSenUQm= zRDUl%HtuXb`a$^rt5#^$EZ{p#i0R($OL=>`E2Vdl6BJ*V)|p;U81MCb;ysUTH?ifW ztefX?YCn%_;raa&*G*~Jd>~V|dayB6aoWB2;jVvr!o=1q7hW;x*c)Fls+Dt(Sw|$8 z_&QHz6&1Qy*kDz3on0lZ5(${11=|~jn^qT4i~?C*%-lcWF(Q1Do$ruaCOl=~qMHWl zjagFtqvMJ3Qc{5tykxayPCk@oPa&E>Zdgit-7ix6;$>2KuM7 z*?50OT`4jgT^piIFpN@Rwmz}VLhTJ!Wn`PM%1yFR?Ax~tXUOv%t6pQRDAjCLTD;I- zaJjInwVVZYUB;AUQOHMA|EOy&;_QEXkzPrrCbWSMMAF$Bj_FJ%cU;U#-6p4& zO6(UsUkmE^+>74xd~~(1j33G!kz<^xSOf!{EQ`9k0E=XR>rDJ~) zT{o5_CXRk#Zt-j$F3spy<|g!r8YuOIQ{5gE*8!86}=F*AI)M`;3)DvAiv-ACZuu&2^{WW@5>D>hBQ=X3Lyq}k!nKrZg`NWgAwRkzPBALL=br~W{IbP>8 z6k1Lta&n)0p7)U%YMY9s9!eG`z+rg4#O)m=$P$qut(n~$EPsS zQBz7@T~6J$cT+h;y-60PZo5HAO?!J&gDfW2Y+?(_ME5hELm$OxS5i4Dy;^A4Y+YQ7 zM;BMAay2%vG-t^$N*A3zq)gRGlN#pt!S{=c0}Nk+u@Vl=%^zvb%{PDNj~IW)t!$Iy zn4^FTbut5^L%zCcA?>|r<|dWf52`^C%XMS+-d%})){UBQGhQ7Q%4 zEp(OG^3cmJ4){@XL&DON3hd@&PXyFk|NCOx{N(ZGzs)rtX-$#$>H{-pXQPFGKSwUB z&83-tFgcbQ3vKhOxwL;h7d|vUw!Q}okmGFYo=OA{91vZRtrghQ9N8S&GlXnudzl|6 zvW=}FsSg|707rDL3I81S9!rze%zHW+lGgq7sb@Vn>?VUe5v{Wzvx?V}S7C@Zm&v!e zw?SoQA3pTRp+{t5luIbfg%oYvGuH{;sU8l z9N9&Wp4IMVn5`dE4Eg7tc_QEQ2*VJl{}UbyJ1e7&pdBonojp4n;BcLpfq&u81Hr;S z&;T|Trr_WCxt;k#4^xiT+1~bicz7Ia!+-qsp-0ZP4n25eXa12xXIt|ReWZ}_5M`Wy z7(Qa|#fM<5cMgA@?d=?1oNLZ6Rpo9k&O@fNy@j3mvpvXpXmM_S3I77nJj_L~vIQ!4 zXpA|UM<~mK06n-AU`>*(T$`2m2;|*SRKdx3c5`kno^PJrT!H`Lv}`^QJW%;zMx$}B z+C>3D+`rAO|fq{h~Fj!#tcEa#|s-NnpOH~LXWu7RaQK6Sr%?K z*0~i@Bp-itv_ZQTtZusgK{x%n!z|B@g#po}D4=i-@t(`MZ>P>Y^}JglJIteGfdM?( zw@sC_1AeI;13LUXePcJse6~;>Hv2qmc&XwbP4QTLA%DK*bFSjGr;-R!!+)k``Nfl+ zC*voD(c@*k$LO7Mp3Qi7NU61T5DuE)jerC2>}7wF1Dy)pqOdBDj2D4t zHkTT63&dM?=7B*SS_%rOi;%X6OCDJraJu{7-IOxP>XLYOd>}mn_R<7SIGIRf^X$^pdole`^fkmEx5nY6({Sv$Tf-C>F zcNKrOJA3TC2-J~rz~5uPMZ015Thjio>G#ol?zg2jvQMZc_5b|7H;SXKG>iDck4qKS zE#A{&aF@ZJiLnQ?6|%V+LyW#m7T);to@P87 z%BvjTY%96C=6hO)GV{+sL&gM+QWM_|!1{m4`5l2706C0;4s+Pz_abxxT~H#OuaABS zXt?0V8f+5=%Ow~xyDB08x27)sha69QbVk}>k8vdU)G*=A#l=89?qXd!?xyQ;pCV-- zc9u4BbKQ108F~^^nJ#?KsP7WKU{;+DaKptNR~r}jR=E@ZR!^k4LOflJJgy8-s1bjr zz1CCbT>PyN^)>+gQOmjgM%Ak+wP5`)EQ}i(a}>br6nRtBbd@VT4X54KFxx~O9e#g6 zrEFvu8{Yg}DEQ=7@DR%}-g!J-vTFB+Ph`XMxq8A#+*Crby`eCx3>apni5lnGryhHX z9+>lD)Vkpjn+MmZ`!*DMIgKATdF{na!-2YM{(3Ss0=!It1Aw2bQ*ur){fSx17#}m;*k_z%$b+y+WO2P0{ zDRVck_G&{5$>igY@-2x9i_gBI4m#~Ms$Oq)6vC(|XNCf_}n20nmWL}WbYt3ZEpdDOWYRB?UDVu3NK6VPH7^0NbYNk$!$t$=A$bup(W zUH9BQyS5Y3C=1#!Rt^)$XJPR8 z3WoYPMx@P^<|5Te;OG0q#?_v#WW;S=0%M+-EjH9ztKU$nuO?Bc{^EbtWhtOJCQnSa zri$57@PpG)dK7J~E5yYM%xuBsvBzH(GsF109%#ic#FuPp(5@{pXtN%yU_V}l&5)%z z+!x!1Nfkp6^L`J_qO1iOU&yn8Z&KT8J?xiPETGkP^|Og0JW@Ct$9pcxH?o2KPO^UT z6n#PDE3vYn@`QI1eN2D#4hoUjePkhxnWvI(nx`s(Z=KEm*wTnb%{n+q(=-X1-QhF*WV?J?z?bv|imm*WHZ= z(oB6PaDWc!ic4L*f+($;g zQ<~N0;(qzMzU|#)gfd6vp&yYEw}t)tl@k;?HUV?-6c-^Tf@z!Tk}PwcZO>sci_nPT zFq?xEaKaz{(io~!Z(~tr&P&2u&Y{!HMm^+P(4^pxM^vBJpnpNuriepg@($=S`mz%B zFQl>eFQ=b)9Hf67CP#}tHG=*7NfK}_S!;)7?1kzq>ig*tCKYT1(Ty*}X`dbdY|OVF zoC)@`TNoC4T4$v7Ur1~?@1e?lxO1U*X>DlvPE)rc&x96$-`YvV@T;uHypJho3tNSL zEvh<=yixOAh-1kZH5EmOvrG=08CEn^dPFU|wB=#v6)}HllU7t^qBuv@+`TkM=W^;E z9?KE(@f4tQEf`SdoVj*KgrS{)=?GP9sHwH*DjbUcy$OxDwJ180#3#`Yb-0VRriy~M z*KXATrycK?yY>JFxK1CK;>U~+c}H4vt&ey+mf2lf+?9{bA^mr`pDoX>$2m;>*(Xk& zIQit6ldXUCp7+4){{2&W@CU)R@yU)Nah;>ZJUy-cw&L~Pf&v?hzB;S;OW`1B`|8yY zQxHaLvkwK;Uyy*12>F8hGt#Xm;V9Ua;}Sl=HU}d;nx1ZqBI`BLDXCpqLKoPHsv)QZ z?NUl334(CY7zN>I+#WQPOII*%=$1EwZFFLeZ%0T_wVoJKdkQ#w1 zTTJfIX*V2%!*DIk!aQ6FSHt!2Lbw&43)3(TFLtCkZ`tX5syyB?X{@uT--IVtnNpQ; z*blqmX4nfi!ZoDTh&>hkSw9F@B8>jI5w1on)6*-9{saEf&JJwf(6uDk2HB&LM~x&( ztTKOces0c(TjcF^s&|5(Oqrg(sI+~_V!jl>py1yK|IrS?7egN^2>lk!0QfSuB=>dZ zApaT`iPl; zJQQh0^BwkYhMbgjgT@c%&*sj~JpP%U=1+gg;vt}d{;`S97W%!nxuctir>-B!aEMws z6pWEjq}oI}jiLI++Rn}@bZte^ax-cSDrt$eb`VQKY8VYP5jF!;W4IPzExl;X6zg?* zSPV*~5&VB;(a^7F6~*yL7l%v1b{4_JiZ(lRB?58G0(CoLsy{uw3jc>((7}F$K-hnc zHiPk0Ha!g=8(GwcqTL{b-;IG#U=F5O7K8~Pt(yzR@{q5YoyQw6)AaN9C2Hre4-Kai*tn%w!f!PbW&^MW4AK%$Z}Zg^A3ZMQ9x6#n|9;sWB>J1CxGz zaRjs0%J>+j0-=^07ebhTgzqT2u$X@=b=d0};qV;%6HU#9nQnYUb6{$@u@2>?rvW&J z6%-Yj{*#&K&m_`aZyhQ!t#`3?<`Yq}fU%&}1G)YbFtX-6muk)*9S|Q(tovGL6OhGj>@<=Ez^I)>AcU>sKNo-SpDq07 z9R8C=PZ76ok@FRfU284QpSm~zabqJHj<#SjEiS3)8eWWM&$eF356l8fa@jqzvk0+) zI)^a$VHS-R=a+fg zj$y3?ZTyi1ZCr1JRHPDu01*irgNrDUf+qZq0# zh8s&3HR5QcF{52KONhjS+-XBd)hI;&KbH-baWWFk{+lfc>or zgB(SpogHh5jKd01c|fdT2n;O^!r?-On-q2~Xu}cb*>pY0Hb)Js5|d#Z9)YcG9Ok^r zqKXBY6TcX>&hdXziPl3{KrR^_5}Hl5yf2+0@7r~JCh(b)#~(X=vJHo_ZZ^ai%q+Qk z%bRJx7t&jqDuG_{3pBxClm|qy#ibxrJE5Aw__u)@XS7IIEd}EMW#VXC3E%ChIbeKd zzky2hFCc%?Qay}@frcBt!qyM%L9oBGxE}(eDG4AjArF5DE5)G&>0)}CT_!c4ly-%m zNGX!(+urekel-^DVyY|Z_JV?&^1L9Bs-G?oWB82m{m^c|f|lNv^DakB{^@kt0Z8B9 z#1o^`x~$$!mXjWA-{i`EFWXzah>o7-;O|#!5 zW;2Hsu(*HJLAFab$SFX6<>7Ed5~Xi>c*3lUhRC5wW*cg0aWGC>CrJrjB?ACX1p&gK zID}!8SF5BI5aI;8RADzzGUf=_2pvz-C6FW1B`tXkP46O0YzeJiN4P$QkaF%^z6nU2 zJLl#Ev8VM|0*fRbS!YFJTs+M{D1ha#3Eej6XL^4Yk|&fUF>Ma=wR8m+P->-Gz2sdB zMq^l=0S*ZxIzeFv46bVmKJi9Cnh0GLh`Fs^3hOYx9IoLUw9Xh(u?*&ID$KLL+rj zJGFn3P|e5{$vqMoiwAW4is!hP?;X|(V5y}J~}jjmonnYC;ap)kI_flnRhC=gn6 zxs?qH>#UI7{fQ!7n5c&^?DPfqClE=kYuJHHUm`eMjqUX$@h+pXY+EF#Iw-(yQY7g- zY&W|iu2{O-eQ__slmEaH771nCEgA#VOPqhB`I-c!-cC=;yJp$>q*3Z%Sb-hLt`GS4 zRuL*kmvA24=AUlc+kt%8-eAOe)u6hOGnuDa$0|4 z^X0Xb2+qzrfzs!?>eet?Y^yQFiJHjPp_N`u*cE|1C=AX|nHgZprO>(bsHAsNS$kPD zfUTkf2Z78vVb2#L$jsQEVeIi~FOYPGAWKI$y;9R?a~@_ReMn$gAYS-m%t{4J8yh_e z^cgn4Gu>eZ^SEkv%ustd#Ga0}Kr(;HfI2WH7ykuXET;V{bFsz{NRYx&O2yN~Z5iZw zpWpwYpSV%_Ikk!>6zGceD@ExJrX$Rn#}jmtYXrct)pwP!v%}v%k@iMw)@S-1&?Hm= z^iNaJsR}l*?VmmCxBcl4J#wf6=eB8t9jffh!*?u_Em)klHEj0h7un zmIpEf?Z&RTW@ZM|KkG(IfQotO;u(+QC&ka9~MlF1CV}^U{jHu2CXaTk%st-oe1?;o)m^jzS$qyXNAyj@%h0zHLQiG;5M>24+-sQ60Zw37 z|1vz<4UIhQ2)9aJhrD|4Sm6@_$kZ#={uMa#>=0ejhEeH^x7Ij#bhEF*hep!NCin8( zImXBLfI}sbKN=>9f9!wg>}LPiK{K)z;<#KIzFboG15}WbN4I(>i9V=C5JjLJ`Mm_H z^9Q(DIHtI=ct439)ScWdib&Q7+%hb0vl~Ul{3v5>b6uYWC~CUF_~GM>Ph@eA)*mwz zq+dU^$ditebzePG*H14%BF1GM;sslO7b+uR`za6>_pB0j6#jpruddqp0i`A4!U3~d z^SuU4wibv6IdTXR+;qI!naKA_ZF3dAI|NeQpg>k60n;?E9}x<#?6+#$GO^~}+Et^@ zVAT*FwI?XCsMUxH)MJP1V4HP>e9cgr`?_ zGD?GSB{4^=)+2utt&@Qsd4wg}2(DJ1#6mup+vK|*F4!;cjQGBiG6fBZ5FWTEAQtd6$3X>;% zmXL+O;INyD?|zMt$v_r7_lpV~i2#T+0z>2VY%@=i0pWk&P9}d>t3^Eu@wjyD<4Q^_ z&T81(PpIh3#V#u@)X}?uxEeN!>}nXTk@S;PNm?jqSc1VA=i&WQQHAfR*d=Jk0UED} z44@88B&ztRA@ThgeD;g?*O5GEgVuF%9+P%J1Xj|L$<&-bx&~sgy7h+EkOgPoFi$n{ zhS9G3Os;==J`ka}80d*>#Y6VSV76fk!A+{yo|+5$>LY^W9=a#~42(V=!qNtDS}lly z!!Sn3wjJiot>^_=;K>`qq?Rd{x>m!Ji%rzAVufSHzS+yVo9gji3Ju1xRm1P6q~q58 zso&;!=iJ6Uvu*awurQWw9!tP0;tTxTn1v>J*C&7Z&Q5)f{Itq*hM(n|koRJ;d_El& z@^@^Nsorq(%w>s8r-Xi6CXOG-Ot|g2jNB6s8mG}Sz%(hUO;nnNaqXfLLPhs6zYs4(q!Gr_xaD)c$*zEs( zw6}Ia29O#e|c!-LQ6o3UjI58>hGTu!M50C?*(n`x%tHCzMQM z6LBhIuC~>5M(+)-L`5NH1b zPl0Lmk)fluKMRX&Wd&w29x<|wFpp9{-$ecA(BJ!Y?$m!9nhQxUViRoIdyKiW*&|I~x6APNnH8Ttq3tKA&+qph!^ zj$OJ@fzF;A9T!xchT14q@A;fwF(`6GAJiPtnKPp^uFhON%UG{Ns8$tJi(WPAy?c~0s`^$|TFD+G3YO{}7PYrdLR!e}Y_h}V zfcB5(pp!PELk}dSonwD=G&;0UR|9MhjqF$f8>@m~X9srZpvZhp1u0tfZ8FOtuG08c zp^xJ1io|}kQNcBN06|ox9i?GN7sO1?+eqXOvO(gvOWvlKQyIOVJ^e&91mtmAYkhKx zGp5pEkC(wm%X+d;HP%BjL#>pFMy1Ond%tc;@j_AAPnx z|4?}1*=L?;&p#X+73S)V$P3*&z$<$GGzG>0OTWS12#&5sY@FF(6vLDr%49Rm(7szCxDL$j#$OY& zXS<~-P)wolIrYN!qwuLwTM(8@FS|IXZ5Y09U@&b`S|u%tkcu8SEn5C`|EVC6(em9z zBp=vl#1nr`@S#!}S-MnRy{@3G!uS+hP^qGG(#1+TlR8|=T9dk*KtJdoxv8FmmrUwWGEgoCle=VA+`w9Hx)RpD z@4XhkIZxInXLVZhy~Y!v!#0WP8xLChtw_n*Zv-I1x8@UHLP#=`ZL6b$}|A5rD8km*pE)v==6Yo@6B3| zJFkCZr_c5vz*nslm-QDaQXHyaCoSBCp(xoZqmGlkzL}3On1#IFkb?YxmJ5TB2nq9bXulL@ltw?#8mBaF8+KXJf-NLp6)?nvYSzPESXGS%&gG# z=$<#5+;yZ6J|3}~40i6EY6zIINL0HOh+%*5E{g1i`=`7i0W~aFC(kY$aZO$4*ws3u z+ytLA=q7r{& z5W-z#!p5t7dM7yN*}gpYHg=sveEH~Nn~@4wPIeoXGwHn@htC);TJOK;9*Y~Q>O%9n z2Pd@nTvp8he>rnGLmdPO^rVYrWuPZf^1LG(>-syy4(Hu7mqw;;}IC0iF>CdpY)g08HHILJb=) zyV%w+aq_H1E<4!$bf?C(GuRWCt>h8ie%d|nGJ@gzU`||J<$Ua}Wob9T&f>au+eE|A z&|QMYhekVet3kj}iRk))%D&jha<&a}cuyMWF>a67wKva>iBNE?9|-bT3nKQTUCy}mVZMl+mT7|>H z=pMe$?we!sbF!;fj%D?ATg$L&KInTuisQQ*Za{l${ho2|oI{UlgHw5pL9K2dN{hiD zJ|9IU5D0QhkhWRpX|;_Gym${#`$>Z^80cNk8YB05M91t#WjZ#BjRb%9DcFmg0)5_P z9@7hF_;&KJsE$|mh8n?R=m;KoSy*2-oU|F6yH>Ov7w0m&YZj@%mLGT1!w0KS*X%x6 zwdYt1bR;*Of1YFbdik0>DT#*@I+bVZ&<|p>@~R*dwa}BYEq~W@PW5)LsP9S^tOq0H zY_B+@%B{@*Ps!GD77u@WTn>3z;r_2(aru(rR0X9A;>Ep4)~ajTWN9wUj>-mqUKvJE z8CZgfHb9D1K!rCir&TOdaVJvN2xQ9MLz?iU7nCbcIZlpjj5+Ly`B90Y z(8*OaIo%Ql6A0awjF44m%nrj;*|3{vP+y~mH-bVtS{_BAZCrmj1DvT+TBQT)kULVR zaWpY010UX0&`H|(2pLI(X3yMFVfIzBUFFSeam;Y4F?V$Dv&`KQgd5Ydhvy~M|qNqf6O1zPdNP=QJK0fN#@6&U>VwjbS zjI1hC)?2p)49Vbovm%b`%^YzvCx=mJr$?g2rq23uc`|>gI9#*glOFp{hR?>!r^va3 zWS#f54c9m(4+X~xO;@e!uqlL$%*Vx~Q}$y2+C!ri<||VQ$gp8;Vj;St46CT7tE)0( zO{i}!n4~P+1Nsw8tfurX_SLjEQ45+DWDjRu)#)^LGgr&wDSNN_-i+CMtCcp7k}wet zYpmaZ1pI$~4s!F(i+9m*ewTJ z>K%M`(*aaqi#;epoto zHZhD>u5Z&PVG5f$MPk)qkn$E;K{UnN{!9{X(@QEj&SBV-OQ&*Zvs80Nev#(H9}Ryh z3Uzm%=$Gq4>(>u$8UYjt=HJ&11om&wXv63(So{ ztz75#VsK6yr;$8hg<%2_5s4&&U&)JJ$EN}qujW4;kJgIDjHw2N7?jL`6K=$%gq@M!@)!@%vg zeyX9@HS`M&y&(lY%fNN1>$<7pw;KAjhJLT1-!XJcTDti|sq{rjc~$3rO}>3jzP%;D zSEV9B;g&(+hZ_2ohJ+BeuWFp7!CO-4oi~5O(A`%EQEK}ogid0cf7Z}z0^NUoh5Ggs zfz-xx1YSk(;{?8CK&s$hv89*)1mL4IFt0Im`|4*j^rD7dV(7ikGH^q3-S{*EcV5QU zPEch(X6X7$0(?P$FA4A!2HyER1GleArW=xU>um<^zVcUw?!0^rpvS10*BQEf^-Bz0 z|C&zviiWivSHG#DZ_7tXx-Kd2d|B5Z zh+Y3a1Gl7|TQBKMS9Q~pcIyq@%qvpEcXg71q}Cf>7vO6Q+<6%X^P_)6lbu(6~3juy5z;7k0U>aPWQ`wI-+l#jP0<<^&U zCV{T&a#yAH8{c8z&dYxT=pPB;Uodq2_YA!E1qSY1#`*qFl-uyK~H(rsX%gDl?q)L9x(9Nq1yer?{`33{Gue~VWKChEr zlBCb+q%Udc3k-kV`XK{1t}t--)vs&lb!nOkQa_PLJ*oPMZ9YXP{)VA_M6c1;?1S90C@wE(}B+NHr;ztAn~ zI;EzY-;hii1Icsahq~A+8v4G5%-2^n^qPh=&ToHLS`vROZb}#5(VzY*O}-?+4;Z+6 zs*=&(W~qba z+Ut_^icb2WB>hk){ZvD*Y3L1xZhcqsOZ9i&{3}CuUwuPEFUr@;D3?4-sQsRy+t+@< z(7Uheq+c;~>-+NUHT~_k8v3<-{3!!Bq}&bpbnAbw4BUP7C4pW+#Gd^(!Uu=*Il|`; z488L`0lqK5e=+dx8w}jOc2$yop_AT{q+dz7R~Wb{72N!e0N)ZoTD$%BPo?~?1^BIG zy3D|>Zwl~j25$UDm)DrQtI-^zQF< z(n}h8QA1x~=+2wJ6X-IEFaJUnUuEd_TVK-9R~Wi;8ClK0Qod^p-G2Lb483!Ofp`C? zzg=bMmSnp9mQ?ZXRh`S^|2;!D{)d70zNUY_{gt6Rmr*kMH^SmAhTgr#!0orbE=g|- z@E85Cu6>~TLqM;uPboUkN zTSg$Yu}L6~b$o%qw+%=YY|#+m&b~}T^cjY3U;V6xKBuA2Gj!uq0!Xg+E;DfFGR~PU zRrXniu76&DFADHw0lvz>J3nLK_Emq$bmI#Q-1;*EcVGD%Lw8AIx6^GjWS z!`t%hzZkeB?cDmj&U8&TEorxYuA8|cHGEGe8Axhd$iUrK zCHL(=T$8jbe`Dy*Wu)aA;qV29uK$F8f!kMqtf8MVbn6E?$z=PvhJGo~Ti=%2q~x79 z-_Xz>8G29ZxPi1=yFeJBfRqwOUu5W=UkUKv0{ohR>pvIZmjdWKzhU6^RSmr@Ro?tM z1GgmQ)|YiAfv%exq|*1^kZ*4?aOW~klNSi#FEMoe4-DM=Ed%d;k%2pxafdj6PuaiB z(Cw>lGIaCjI_ZBHy8b7f^aqA+e2;-UZ~lUzyH`G~q0egQa{|5kV<~YNCvKmb{|ZCz zeu{zXZwc^M25w*dlZLLz$3N?&zi8-fsq1e7e1?G=-)G>xUovp#%^xvz_sSOqdiB#f z?eh%Xq>qYdC>O31)?a1l_SL_C33Tn#8u~0l@4YF&Zy3098JE<6>i8N%H?J}9?u!h( z^CknguYFFweL*LEUXotYNnh5`7a6+oDg*ERPO{6VyRUvjLq8E5a2N)vmsm0*4F8j% zcYY_p{|NAV25!H7Swr8@(04TSEh+E^NxJq`hHm}0PLhV+{i;sVm0gp62Huriw|*nQ zn^OB9CFPg8WnHJ#bn|7&q%n{@H-4mxUD42gX~=y2frfspA&v9f-;e`DZ(?yEo7(Er!m_5a9` zRQKQcD`qFep1$pw-9?EKX0}-w+knA7TV7iv+FMNTOz&==XSc+ z_f;oP1&1EJB13P#suF)GL+}0@r~O2wy{1CH;>4fHz&l*- zPyZ+bPhb0~4E_1vzs8{-Vs9%UcA?BZp{{*LhW_v-2Oe?YEg5+G=Q8l*P0sZ8FI1Gu z^-C`ITN(J@A9CP(9QZB=e!%75`Wcu16$f79Oy8D)ce#^)@4g}f@BCVoS3P-4b@Q!X zsn9P~=rt93RrURKZt`^%^&1s>Lx%qJbs2d2GM0QmWc#iRJ$dtYD)f69`qMXL;Lkt$ zF-QHgibA$~AkGpvNGDX?D>C%t(LborS7hkzH&oQuROqWJ^gR{&x(q#i?R5^ljMRNd zO?*#=o;>=0h6??Q3_X1rrI1s~_k9_9^49Az^oQTcz}vr3X>ZEVyPWCCqi=Hd->Y0I z|07-N8#46Hf62ffzp2u=o4Tg|uAHNBq_x_1PkN;K0Q5(O< z5DwaVU&YWjIQ00}Dh_+_-q$gN^3r=>!LR%>QvYJx4@!p0ND7b4XYEuhZ(=cgyQq$A&HAOj}y&;bwwqwFuM_{otutUMy5;e-J7ii&h zb=%6ea5XAykA$7S3PN_ck&dda2O6j`ZC&Aw#g=x_=i=ScD(p2b!Dss9hcYn zY5}0#@@&^^&hO(jLCT$734h?&8VQBBzJ@=4ZSZ_DR-R9a9=fR@7h>$q6G=zjIO=B9 zx+^I=J`j*7`<+xdLW$6`2>h0v3VLaY77D_cJ5ZkLT>mLp%wtnkGoMm6VJeHz^Va|c z!W^v0>kK(r>ZB1m1g1}x$O0*l-|?B0dQ7NObg-F@23-U{87r-^0(b&#t=Q9X?%2A2 zp$S>@H_Z&KWW?No`sjlXO1QroNxgDanD)SdtClPJ$K$zXzs1}6poeoWgNkTtq7nKH7l*B(^wI(coa5={* z%~;9jx!{r7x?}0bmh{&Z48k?J8!4HLci76pmZ%J1iOe2|)bhfn-OJ9jXFVWg>~-{@ zR>37QQ@q0?y$^9X@6Q3hn$GFW3(OOv$ED)~u!voi+taj!t zPz`8mPNyKYEp#6nCdy1mFX@VM=t%rd&aqkGb2jUEm~|zn%(m3A_fwur?6J{LV7a`a zRe|H-(DA~OST4A-`gb9J3z#Gkoi(W8`qXo2(16>jAldw%2TMgpjvGA&2x4J45c@gK zq?s_(M_33LKob_+=LcTK$ns*T6&urRW8#CBp4%LYZ0*5 zuZ%}5@5DgUp|Qq|gKz=`E%XCIy`1KpBaojYbhPL0^m?iuoz0>Z0jcg?Yo-7pr165`?F7l(dsU zs9u`A)S_BA-IBM+SjJnHSo=@_SeF=Jo$R#PB{l3Ba;6%O@$ z&Q<41^aM65y+08YpB}nvKI(DmTiSNHp0r;IjR0K z>{h@1>8p3z5|+gn{a|1j$I0cmr^pP#q0e!;O%)h|457_`o(ZX_Lk?h-cV?u7SXNXd zY*+K(j4pll(%-dY*47Bb?<}ucd>;gVu`;~3Bm5$n?~ASb$!QCLzaSFgj-mdfhf_;n zw-~EvyR71BQnsN66u`x{BI2gg_Ilg+4INFFa>z`dA$|X$Pi7>Z8pLGQ=H?B6vfiW^ zll%|=NA$0Mo{;(=1>11wEsax6oH@{yd?kGe`zxre5F@m%WMM0#xws{{l(=2uk?WyG zqeKQNujgZ~HRGZ>x_Q#jks#=kgPA#^QxzYSerwQ)57I@tZj-<`Se6`}h~MIPcqc{| zqUv;)^5Uveqm=QMWVtj$r|zO0Y*DIc&P7#*D6hkR+l3P~4`64V1H2@6YXn^i$KFjl zR(r7AGsiBfk~Hcb>Wwd%cXd7tC!*PraX%qZ8gGtA@I~nUO>oPQxJB?z1iy}f|F_JK z9frnu2=h((v55C9=a4)~6`rG10S75KM~T*Q!yoO6aYdoyXSl-Sc)*g2#|)UlZFKc> z7f4WlT#m~GMWm=By6s7vPD^>LUCH!(D#W>ef~PTbQp<>VE9(O>JR{90KxTb-j#+3L z83N5%T4ZC@UADIdwj|J%aAXRtJL6r9QLNNKfV!EY8+2?!m(YEiqFdaVCV@F{2f>Thih@RH!9s8W+`pamrT;hoBV zdI$2zA%*9zO8^BgdzMr}+{iv8(PP;xaL{QA%P;%9Nm|s`!@`=k*={gfX#gOy@gfkH zg61%K4F!6Udp@zK+RzH>s9OVE5Ct9B2^WVW2<5PF?i$lsgRJ?}<6D8tP((`{{IA7q!KIl_3>TH->O5n8BWy^VYx%Y7QIXfT0dX>a02@ zr~}M0gx#W??7{J-vmTasFpWDS>og#6L58z{Z^0*9odP5X=(s9cu5JX#!T1e9A2wtG zfsO&$XR0Kh&0R~5(kwli99=_zo$K@+uC0B2Eg^E%3o^+)RW7%V_-Aiz%1Um3k!0U& z=*^amg)&DZCUBuUdA@xJr;awFl9&B6Sz*7S_K*toB^N1d3TL~MygP^b@xy1NeyyOQ ze!a>MmiiJWvfd6Jri_94L_@ao56tx(0Y~Jxi2C{sm4C3~qR`8qWo(?n&iJ@hKhqdV zCw<0S@Pa3EdF{Q$w{HFQ!TM%@-q2$h&rd{6iCg(nLueI7@IHGKn`*}a%LF}g`o=jD zk(47GCk{28B69!op=p04#$8mS(ovINhpGYTRDGHsubw^SDepS2+d_8SH%g0k=z|$9 zG!z-P70vbT;3^C?xP@Bs6r{AX+bW zsxfN+uhCQ28vI<=&{8v7bkA(GRKj={aJX3wxBmP%sHU9Q=xFi%LQT#*4T;aOu?nSR zuHg~e-lCM$@>Ea<8C(MC)rA6FpNGgA&UMW<2MRS@Uk*an?M-*X>`onE)^^v|4Ag2n zbvg%TEAWe>MkAkcX+e;G#}h)DGoz-{PSGn5^Aj}`TORDt2G<5+ULU5Tgn={dVm{{y zW*OSOs)bO4iGc_2#TBg1i7Qym!xc39qY2}EOkP=U@@k+KX8h1wmV=JDk`f-(K4`xj zP^V915;u%BzlDYQCMCw*atone037T}`zZP$xc#sp7oC1Nb!%0Bkg8XX5t(+KbaA9~ z*WCc=E-D5^x2qn4c8cAB2eCh5RlBTL9#c&Py4hr1i$%iMTAD#ZS|!`$BHVv3mCfM; zyjQzL(t1R2bneK?MRzP7E^g#SVjkMB>u7$Mk~xvpmu3pL2_=`fReJGEaT1vwsgzr0 zo^0Xd=0aM3NE5hfG z{)T*p)x(Egz%XfbHT3KxYV;FlXdGs5&_TkQr6U*8*HyoIM^MQ35a6xTbo*X+VIW82 z-aYmw)!G2dUo$I3-O!JxcPoN-YfI*1U=jX1^V5O(;r1etj3C%)hmm-vm7rP06v*%4GLy%TX3|SkVoyjNZAvju&Z$M zuw%e~p?1tb>rB~EPhl~fgGwPV27}UL!C>f#lQ(pAx}q{&9%(r4JnZkwv${yTp6sKF z(y0@DCqE|k4?>bl3eUq{?08^rYBLzrtFC&dSoeNM9LmX1q*!gY+N&x3n>*$ozGWoy zEhEktH!Tw0F>V;#qG@o`#e+LI*U-}SNoJ9M1tW+ek~;1Ox^$_F0;)3Jp7muSwCt=E zoYd{cd+5$HP>Qij71~S2`H4`Mos7rIFPi>*mhuKE?3-1U(?g~b_>6pxyeOTd9a2nx zLGIZg$4W)jVQ#mS_e3QF(~ZS%?64@{VsJupXjk17MYZHfIl5 zbXJg0)KV?>Q+ct?PbJG;#5I(6-t=qL%lFD2Rp1!JY!KBiix*Ob__iX`M3OQGYi(a=d;%0VP zoE7}o2>FNM1=fE?F+GTFn|-5ymkh6qODkL5>13tsrh4r0Tq;zP%MWca=CwLjYC+Bn-@m}epMhO%j5}L0V*PP(6Vze-&drU0StD1HU|~806a81_ z(P*6NT1vwvL^`KdCY@;Cv)C$E>8#nMq~a4Ar<>U}BOo-*@DG$Zd=|`qcwDFGJK}4S zk@?2uw|Z_U<1V*$7XRr*afx6L)QW}GyDG+?OHNU9@Cf8&2nH_6C7+*J#rs+4V>)_7 zX&8`n<8QMyyut7~Cowhc`?X|3{9x08A$dSX)E z0_qi;F1FgWy91kdD=%7j-KHBZ;iHUeG7nWGy+k=lo~K{_DU@?GNj&su|9w7b4dbkp zXX8^T>_8V4U7$yF-DiBgO2d6hQUOg>^V{qpvev`rb2V)H`6L^ELD$54oPU_NIZb?p z?dR5$Us&z8Uy`)=U|2gOR7RZSj23z_PMk=E6k$i(Ufg;OF3j!f zl`p^sH(71N^R4Y&34WXYe(yLp=suvCY34n!8Q&=L**&p@3Ny*sM<9t;H0x&hAUp~mgs0)X@T1{L zxEEduAHv3PCEO0LhL^*e;hpeH;q~yv@LG5)ydT~U?}j(RmmF;?DP;mv;u%g!RQ8kH z*tmlf@`Bh$J5{uATW$(JRdNc1Xo!x(bZHbH!z!anqL_hy46;?3$N&z~GFRdRLNRj+WkbLU;$xPE?0SVRG3zzGT-?Q`B3wp6f!_8m7teWiBf# z_^RhQ8aCCRVs$uw>ndu!Ujp zDVSJ_WGp>@_*$_tF5epBk|<_XngcSG2yI72N1@4{z8qFtc3ODfAe^yApSPM@#0%E) zaNa6z1O{)YL%A^vfn(*~64Ww8FKVzPs~K2Hi1beO0%^QXHV6$1pWtbym_2HCVtAKm zV6B7aujD0TJk&ivDee=+QNT&jkug?r#VNxF5Fdws8nv{2M4H>t6z#LlRpNGFGPc^% z{X@J}&k>#WJ&_L@*|(O}>YbY!-lO5u(#W&a@lmRSzu{SGI5EawU1il7z)W&D;Idna zb-H~lVAexCaL(@L$OY#tvqyYTS7Pdo(dR5Ge4 z5zf|s1Dz1<=x|u>3X>LpGTGSd8#ddjFKn5L_=*pW$_2nCxM*}pm$EsJ#il-7PahJWA$*1ouZI$6Egw$GS&@p*(d@i2Ez`NY|})Y^yN zd-3po>m-E(2xP=JY=rz|DnvxF37KJh>U_G;xP*sd z)Xd==9CA~~B)ynT9V*4{nWJi7n$A)USu{5B6Bz2Fv$pev7bffQr;Gpn&DGttgV5)H zYIP^solcd%X8xAwOit21$k6T3`LaF>*6q;RY5E|`(s&cnk9(z!kx4m>kCPj5aes2$ zztl5-hD@G*5=vyBzH82mQx@;U_AM(~#>UFX7T7RbUfj%)+{S-(L^w0=tfMByddd%OsFuiC8$S;;rq{KJ=400V4CF zGRDwG`KXd3;8O;X@@67>=$xv9b2A?%N5GzvjoYDkl);DLeEcA3&s^-#%6kug2a961 zv)>!WN6DC|odmm)c#6b*<(|aCp{rCvztMbTpW_NN0D;->Hv*9_KzQMy?>P*MAAKX@ zGyf^VQJ99u?hA-^@6J{~3Gd}n4{yK7j~Jnk-)%T=DltdRNXUY^ZV31$EhLl;Z-?)p zJ8ijMv;*Vp0hzCeJ7(*}%RGXA92>iILmoPfc&>eo@9^lh>?n1c-GLPM%=%67$QK_a zb3RA4wfyaIRgeXuL;TQxJ4iaCzBu%9 zMGzi4@Qjkl?hw#PjS1eT?DIv}Ain%!3sub0y-Ag{4&xF8ngl_#QKePTF#_D7 zjUt+f6~JOy6qS6);ba6KRO#V3a=t4LV3UruyxZ;U#NC&61CVon3)rs5v)QP(pY_Ck zdf`HQqt{080u`k@@iBbZ#*SkbK_9hk8<*hNCi6w5R$@@E#-C#?#>!gH3Ozu0e5yhG|k@n-{K~nj^ z*sNNTT}NNOCObKQ*-0VPEB6dhq1-lZR-%ygoN_-ob*x~A;e;{Z+$U5CE8$;#a0O{h zVtwI`gJaI-)2T#MyvN9=*G7bS9#zvRU){3+h0@-TOtZt$LR;$rqux3;iNFHugGp_Q z!wS>Yc8i%_Gjt>x*#-kcN5IxH(n1x>WTq^JeJ?t;&3Isc!pR6lVm8scM-xxo^mG(x zSG{5P`h{Cp@zi$iwyg|PIhS2X^(S=VSqZ7*ln-SW%V>@UmO~%bkirg@4INaOtRhbL zRJ7AOj_1zBp3d2~)Z90=_`|NnPS-+rbR8?E$gIKXDaSe;W&AL^+oIEB6TJ+XQMOtd z`d?*q8iF9%d#S#-` zh$d%E1@SN)jgqVz4-xP&-NRFb-uTgEM`VC`OhOv>v^>p*m(-@(K|niqZQ#W$6b23g ze!t^HE2Pc|gFB3%DihpcWU8#_<<7G^sBdbocGzHlS$s$eXPhnbN8e6IfxyTiey*a+ zl!@aq)>2Y3;|mZtxtXd_&bKAN zN7d=ru=bMrz*|M%pIy?SEpF5Kmue-A5=R4;D^53~^(~>U+E0aAthkTI=7DVTPLJ*q zpn{P~*sA(c>IZUPmZ{sADr7F92`hIZ<}v<%D&xw3g|Gbc!1&gIMu*J#N`KHs1@m=~ zK$XNBZ;l7?YP7-VSLIH;tJ(5}Qm~@HGshbu^>iBzFI?EzjD{@M%BF`q8@n^38xD(@ z3u?_s(p<2V;i;=nUE3lTf>aGN~etyOxKBJsKr#*K==A_Rz4?%*vgUr>%H+NTie( zd=06ccAnua2P}D~(shj4%|P1N%Gq^eBJ5?v?tp3#GU4;d-sjS)G5JRRlAAVQkS6(2 zxr`^lC9y^+6-HC=vD~ZBjoQ}a<%)WLGSG29KRnZCQGA@BOZe-+e)yvlbVW}Dfjlx< zlpBqRY?wU}t`HXH>9nuhyn&;8BOj&vDP1_p4++suWw{ET&qv8M+M0|Cw$E9CP`h)= zH_k;RdbyJ^GbW=s#c)ILU9 zYJq-Gq-_OTFX}?LkPRC}c9Mo7wQnX*PN_P;Cm|ZwEJ+AkY@JJbW%=|z=x&L@^I9{J z4xY8K#jSYlr8CobW(gx%9wom;a&{h*qI!i%hEnmf*QoFO&01ybGk&(ePQoU7=6)K; zL|mbZut5W_;f*vC$RRwNdCpINREdLnpVd+J$hKW>!J$BDsLZW+4s=K55rUR&Ro1nj zVGYOS(^o$^OoxX9O_{9ZqdFHUFPZ<0cz_dvO_!A?5SQYe{DSCU>8 z7tqh?w0-l|oohFr7oHe@L}V`mapHM6rHj;0-@bYGmN#8IJqM&h2Wwa|LOG;FH4O7N zAARhn1y2s~u3#qMbAsX6Ekl29tWYH%T8t*m7!Bx5g@hk745E$AQujW^vgZeTFk~U` zIG7j2G9L`g8FFu*mQ_5b3Jse+ZEo~iwBF}lU=-UW^_7K^ESbcA1(t;W$T^1goq(v^ z0P5 zGS~TyO)pDuYn+eHoI)LKb5d=YbBbR>Fu`dJBWrEwUCxh0=gzmGZ5im)BH62Es^!)q z@<$%eRgOh*-LSuZF2h(gLxE4>2LFERRzQnp<@)VQU$OaTnqMa4Q025-#N6LEbLmH`4)(#z^I5f)FK zWZstLt#O{gKqI|it8GnisWXT!ELFeQYoS40c}R+%SZO+fGEe~5J9>mC4|Ys3uEz4E z3$U04wKU@Zc20ujZBNDkR2fQ|&nmzynYyGgwO41Sw zrdpSoG&taYoQ&T2s?e{&XLuZRFX4n2WRL4(n~9rnnTIumr}|Bbz@TZmM>A3v-J_Wv z<Ii*Fi-5*G17OSc$>h9}Pb^3z>%!1~eq^ulq4y;1d)4!Gz<%Kq7}off z=lHcY`{Qr_iuJbVIe0q?4f+bpNl@2HPCQ=#x!Fx+0W}E5Bfg5$&*myhy;j%WH=0o7 z8(_-os4rePc{F%aK=Nj?LY_G(@D8AmXo+HAG*;sKN1!)ctcT~4f!eDcfJW48#=7fo zzx?cfX7dW+F^((+9HDU2C1Aai!z5{dwKWyB>&5jmh@rvbsaaV}v%-%NVQDsVq!08y z%)=@y4a?aS6}V&xRv6oncTg-_wA^ZSKQ9qZj- zAQV_6z`A||@;*6ML3LQBe^NP~RhaJ-!AHjrw z$)WBu!R>u!`%tRp_i>$~&}@e5VWfW7CPtvuER2TYqYOx~ zk$MoPV-){U7({wP5^V}Emc5Tqr|w{X74SEP*0OXTW|6SE!U4J{O;CmIG=y6A)?oQes&ef`C|FWK=mAWc7%Dp+PY%-TA~gu2$0#p6xpjSibP6G9 zc^^oc4WWNXTgi=ai;=ck$8mMYoxWCG6g(S`9*A=ljukBIKqUBZQ8|zvYYJO?6X5av z)+rodMtRsuiJ-Xu;1X5|E+D8m=}8q^P{c+`^b87#7MLtVCwVHuamM?yR*YILR4rok zwj{6Kd#;6mbwZes-*Fp{O55mCh4wxWsCE15r7JhCwmOGZbzJt>)(&6*CVQ{|9IX|= zKqc&mGV5QcP*;2`P^b)O;X-j4@?!PzUJjowwWXnBIxBTR{uzAa{{X7Xt)*@n766ON B1=j!o delta 51784 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